プロが教えるわが家の防犯対策術!

C言語から質問です。



/*
main関数の中で初期化した配列
data[10]={60,30,70,25,20,9,92,55,20,10};
を関数 keisan() に引数として渡して、関数keisan()内で

平均値、最大値,最小値

を求め、その結果をmain関数に戻し、main関数内で
平均値、最大値,最小値を表示させるプログラムを作成せよ。

int keisan(const int data[], int data_kosuu, double answer[])
{

return 0;
}
とする。

(注)
プロトタイプ宣言を用いよ。
ヒント:平均値,最大値,最小値の3つの値を
main関数に戻すやり方として、配列answer[]を使うとよい。
data_kosuu は、配列の要素数を与えるものです。




ヒント: (int型の変数)/(int型の変数)=int型の値です。
int型同士の割り算の答えANSWERをdoubleにしたい場合は、

 ANSWER=(double)(int型の変数)/(int型の変数);
 
 と(double) キャストという操作をする必要がある


*/


#include <stdio.h>

int keisan(const int data[], int data_kosuu, double answer[]);

int main(void)
{
int i;
int a[10]={60,30,70,25,20,9,92,55,20,10}; // この値を使ってください
double ans[3];

keisan(a,10); /* keisan関数に配列と配列要素数を引数で与える */

for(i=0; i<10 ; i++) printf("a[%d]=%d\n",i,a[i]);

printf("平均=%lf 最小値=%d 最大値=%d\n",ans[0],ans[1],ans[2]);

return 0;
}



/* 合計・最大値・最小値を求める関数 */
int keisan(const int data[], int data_kosuu, double answer[])
{

int i;
int sum;
int min,max;

min=10; /* min の初期化 */
max=10; /* max の初期化 */

sum=0; /* 合計値の初期化 */

for (i=0; i<10 ; i++){
sum = sum+data[i];
if(data[i] > max) max=data[i];
if(data[i] < min) min=data[i];
}

sum=sum/10;

answer[0]=sum;
answer[1]=min;
answer[2]=max;

}


エラー
error C2198: 'keisan' : 呼び出しに対する引数が少なすぎます。
とでて先に進めません。

教科書などを見ても間違いがわかりません;


虫食いになってるところを自分なりにやってみたため、
根本的に間違ってるかもしれませんが、
どうかアドバイスや指摘などをお願いします。

A 回答 (4件)

こんにちは。

 #3です。

以下、#3の補足について。

■引数 data_kosuu について

> 1)データの個数を意味している、、、?
>   理解できてません;
> 2)データの個数という意味でつかわれている、、。

仰るとおり、引数で渡されている data_kosuu も、関数内で使われている固定値の
10も、共にデータの個数を意味しています。
でしたら、
  『固定値の 10 を data_kosuu に置き換えてみる』
ということは考えませんでしたか?

関数 keisan() は、このままだと、要素数10個のデータの計算しか行えません。

関数にするのであれば、要素数が1個であろうが、100個であろうが、要素数に
関係なく計算できるようにした方が汎用的に使用できます。
そのために、要素数を引数として渡すようになっているはずです。

ですので、固定値の10 を使用している箇所を、固定値ではなく可変値に対応
できるように変更する必要があります。
そのために、引数の data_kosuu を使えば良いということです。

ただし、可変値(変数)にするということは、想定外の値(今回の場合は、マイナス
値とか 0 の場合)が渡される可能性もありますので、値のチェックが必要になり
ます。
⇒値のチェックを入れないと、「0割りエラー」などが発生する可能性があります。

さらに、値のチェックなどを入れた場合で、異常判定になった場合は、計算不可
として関数の呼出し元に判定結果を通知してあげる必要があります。
そのために、関数の戻り値を使用します。
⇒現状では、戻り値が返されていません。

> なんとなくできたみたいですがdata_kosuuを使ってません;
> ↓の回答は問題が求めてる回答なんでしょうか?

1)引数の data_kosuu を使用していない点において、仕様を満たしていないかも
  しれません。
2)関数 keisan() が戻り値を返していない点において、仕様を満たしていないかも
  しれません。
3)配列 data[10]={60,30,70,25,20,9,92,55,20,10} の平均値、最大値,最小値を
  計算して(計算結果が正しいことが前提)表示する という点においては、仕様
  を満たしていると言えるかもしれません。

■printf() の書式指定について
※以下は、ちょっと蛇足になります。

少し細かいことになりますが、下記のようにprintf()でdouble型の値の出力を行う
場合の書式指定ですが、

  printf("平均=%4.2lf 最小値=%4.2lf 最大値=%4.2lf\n",ans[0],ans[1],ans[2]);

この場合の、%4.2lf という記述は、%4.2f のようにサイズ指定子 l を付加しない方
が安全だと思われます。
コンパイラによっては、lf とした場合の動作は未定義になっているので何が起こる
かは判りません。

■参考サイト
[迷信] double の出力書式は "%lf"
http://www.kijineko.co.jp/tech/superstitions/pri …

以上です。
    • good
    • 1
この回答へのお礼

data_kosuuに10というのが入ってると思いませんでした、、、。
完全に理解不足ですよね;

だからどうやってdata_kosuuに10をいれるのかわからなくて、、、。




なにがともあれ無事完成させるとができました!

アドバイスなどありがとうございました!

お礼日時:2010/10/17 00:00

こんにちは。



> data_kosuuの使い時がわかりません;

これは、#2さんの言われている、
  『関数keisanの中で、data_kosuuを使わず
   データ数が10だと勝手に決めつけている。』
という意味をよく考えてみて下さい。

1)関数の引数として渡されている data_kosuu は、何を意味しているか
  理解されていますか?
2)実際に関数の中で使われている下記部分の固定値の10という値は、
  どういう意味で使われているのでしょうか?
    for (i=0; i<10 ; i++){
     と
    sum=sum/10;
上記1)と2)の2つの値の関係をよく考えてみて下さい。

注)除算(割り算)を行う場合、割る数が0だと「0割りエラー」となる場合が
  あるので、事前に割る数が0でないかをチェックする必要があります。
  割る数が0だった場合、除算は行わずにメッセージを表示するなどの
  何らかのエラー対策が必要となります。

> そして一番最初のデータを仮の最大、最小にする方法が思いつきません;

これも、#2さんの言われているやり方、
  『一番最初のデータを仮の最大値,最小値とする』
これを、そのままプログラムコードに『置き換える』ことを自分なりによく考えて
みて下さい。

ヒントは、下記部分の固定値の10を、ある値に『置き換える』ということです。
  min=10; /* min の初期化 */
  max=10; /* max の初期化 */

■その他の注意点
1)関数 keisan() の戻り値について

  関数 keisan() は、int型の戻り値を返す関数として宣言されていますが、
  実際の関数の記述では、戻り値を返している部分がありません。

  戻り値の意味合いとしては、おそらく、引数のエラー(範囲オーバーなど)
  とか、演算時のエラー(0割り発生など)等をチェックし、処理の正常or異常
  の結果を返すことを想定しているものと思われます。

  また、main()側での keisan() の呼出しの際は、その戻り値をチェックした
  方が良いと思います。

2)関数 keisan() 内の下記の平均値の算出式について

    sum=sum/10;

  ここで、変数 sum はint型で宣言されていて、固定値10も整数値ですので、
  計算結果も整数値(小数点以下が切り捨てられる)になってしまいます。
  このままだと、せっかく格納先の変数 answer[0] が、double型なのに、
  小数点以下のデータが失われてしまいます。
  ※このことは、質問者さんのご提示の文章にも書かれています。

3)main()で使用している下記のprintf()の記述について

   printf("平均=%lf 最小値=%d 最大値=%d\n",ans[0],ans[1],ans[2]);

  ここで出力しようとしている配列 ans[] は、double型ですが、出力書式の
  型は %d の整数型で記述している箇所があり、型が一致していません。

  そのため、出力結果が想定外の値で出力される可能性があります。
  この場合、書式指定子は %f などの浮動小数点数値に対応したものに
  する必要があります。

以上です。

この回答への補足

>1)関数の引数として渡されている data_kosuu は、何を意味しているか
  理解されていますか?
>2)実際に関数の中で使われている下記部分の固定値の10という値は、
  どういう意味で使われているのでしょうか?

1)データの個数を意味している、、、?
  理解できてません;
2)データの個数という意味でつかわれている、、。

関係性はどちらも“データの個数”しか思いつきません;




そして
他のアドバイスを考慮していろいろいじってみたら
なんとなくできたみたいですがdata_kosuuを使ってません;
↓の回答は問題が求めてる回答なんでしょうか?

#include <stdio.h>

int keisan(const int data[], int data_kosuu, double answer[]);

int main(void)
{
int i;
int a[10]={60,30,70,25,20,9,92,55,20,10}; // この値を使ってください
double ans[3];

keisan(a,10,ans); /* keisan関数に配列と配列要素数を引数で与える */

for(i=0; i<10 ; i++) printf("a[%d]=%d\n",i,a[i]);

printf("平均=%4.2lf 最小値=%4.2lf 最大値=%4.2lf\n",ans[0],ans[1],ans[2]);

return 0;
}



/* 合計・最大値・最小値を求める関数 */
int keisan(const int data[], int data_kosuu, double answer[])
{

int i;
double sum;
int min,max;

min=data[0]; /* min の初期化 */
max=data[0]; /* max の初期化 */

sum=0; /* 合計値の初期化 */

for (i=0; i<10 ; i++){


sum = sum+data[i];
if(data[i] > max) max=data[i];
if(data[i] < min) min=data[i];
}

sum=sum/10;

answer[0]=sum;
answer[1]=min;
answer[2]=max;

}

a[0]=60
a[1]=30
a[2]=70
a[3]=25
a[4]=20
a[5]=9
a[6]=92
a[7]=55
a[8]=20
a[9]=10
平均=39.10 最小値=9.00 最大値=92.00
続行するには何かキーを押してください . . .

補足日時:2010/10/16 15:20
    • good
    • 0

エラーにあるとおりです。



int keisan(
const int data[], /*引数1 */
int data_kosuu,/*引数2 */
double answer[]/*引数3 */
);
とプロトタイプ宣言しているのに

keisan(
a, /*引数1 */
10 /*引数2 */
);
と2引数で使おうとしているからです。


他に
・関数keisanの中で、data_kosuuを使わず データ数が10だと勝手に決めつけている。
・データがすべて10より小さいとき、あるいはすべて10より大きいとき最小/最大が正しくない。
→一番最初のデータを仮の最大値,最小値とするなどの工夫が必要

この回答への補足

なるほど!

引数の部分は解決しましたが、出力がすごいことになりました。


原因は
>・関数keisanの中で、data_kosuuを使わず データ数が10だと勝手に決めつけている。
>・データがすべて10より小さいとき、あるいはすべて10より大きいとき最小/最大が正しくない。
だと思いますが、
data_kosuuの使い時がわかりません;
そして一番最初のデータを仮の最大、最小にする方法が思いつきません;

補足日時:2010/10/16 00:24
    • good
    • 0

>int keisan(const int data[], int data_kosuu, double answer[])


は引数が3つですよね。配列と個数と結果の配列
なのに、呼び出し側は
>keisan(a,10);
引数が2つしかありません。
たぶん、
keisan(a,10,ans);
でしょ。エラーメッセージに
>error C2198: 'keisan' : 呼び出しに対する引数が少なすぎます。
となって、"引数が少なすぎます"って書いてあるじゃないですか。
めっちゃ親切なコンパイラーですね。

もしかして、日本語が読めない?

この回答への補足

そういうことだったんですか。
解説ありがとうございます。

補足日時:2010/10/16 00:25
    • good
    • 1

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています