配列を関数に渡すプログラムについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Cstudent

配列を関数に渡すプログラムについて

#1

投稿記事 by Cstudent » 6年前

配列を使った関数へのデータを受け渡すプログラムで、
100以上200未満の小数を最大で10個scanfで読み込んで、-1という値が入力されたら読み込みを行わないようにし、入力されたデータとその平均の出力をして、さらに関数内で、読み込んだデータを
Y=(X-100.0)/100.0という式で変換した値のデータとそれらの平均の出力を行うプログラムを作ったのですが、ビルドのエラーがでて、うまくいきません。
変なプログラムを書いていると思いますが、教えて下さい。宜しくお願い致します。

コード:

#include<stdio.h>
double nyuuryoku1(double d[],double X[],double Y[]);
double nyuuryoku2(double d[], double X[],double Y[]);
double henkan1(double d[], double X[], double Y[]);
double henkan2(double d[], double X[], double Y[]);
int main(void)
{   double c,e,f,g;
	double d[9],X[9],Y[9];
printf("100か, ら200までの間の小数を入力してください(最大10故,-1で終了)\n");
scanf_s("%lf.&d[i]");
f = nyuuryoku1(d, X, Y);
printf("入力されたデータ:%lfです。\n,X[i]");
g= nyuuryoku2(d, X, Y);
printf("0-1間変換をかけたデータ: %lfです。,Y[i]");
c = henkan1(d,X,Y);
printf("入力されたデータの平均値は%lfです。c");
e = henkan2(d,X,Y);
printf("変換をかけたデータの平均値は%lfです。e");
		return 0;
}
double nyuuryoku1(double d[],double X[],double Y[]) 
{   
	int i;
	int s = 0;
	for (i = 0; d; i++) {
		if (d[i] == -1) {
			break;}
		else
		s = s + i;
		X[i] = d[i];                  		
	}return X[i];
} 
double nyuuryoku2(double d[], double X[], double Y[])
{
	int i;
	int s = 0;
	for (i = 0; d; i++) {
		if (d[i] == -1) {
			break;}
		else
			s = s + i;
		X[i] = d[i];
		Y[i] = (X[i] - 100.0) / 100.0; return Y[i];
		return Y[i];
	}
}
double henkan1(double d[], double X[], double Y[])
{
	int i;
	int s = 0;
	double t;
	double average1;
	for (i = 0; d; i++) {
		if (d[i] == -1) {
			break;
		}
		else
			s = s + i;
		X[i] = d[i];
		Y[i] = (X[i] - 100.0) / 100.0; return Y[i];
		t = t + X[i];
		average1 = t / s;
		return average1;
	}
}
double henkan2(double d[], double X[], double Y[]) {
	int i;
	int s = 0;
	double n;
	double average2;
	for (i = 0; d; i++) {
		if (d[i] == -1) {
			break;}
		else
			s = s + i;
		X[i] = d[i];
		Y[i] = (X[i] - 100.0) / 100.0; return Y[i];
		n = n + Y[i];
		average2 = n / s;
		return average2;
	}
}

アバター
Hiragi(GKUTH)
記事: 167
登録日時: 13年前
住所: 大阪府
連絡を取る:

Re: 配列を関数に渡すプログラムについて

#2

投稿記事 by Hiragi(GKUTH) » 6年前

先ずはフォーラムルールをお読みになり、必要最低限の情報を書いていただけると助かります。
だいがくせい!

Cstudent

Re: 配列を関数に渡すプログラムについて

#3

投稿記事 by Cstudent » 6年前

1. 自分が今作りたいプログラムの内容
キーボードから100から200までの数字(小数)を入力させ,入力された数値の平均値を表示する.
入力にはscanf_s関数を使い,-1が入力されるまで繰り返し入力を受け付ける.
平均値の計算には関数を用いる.
関数へのデータ渡しには配列を使い,平均値の受け取りには戻り値を使う.
関数では,100 ≦X ≦200 のデータを次式に従って 0 ≦Y ≦1 のデータに変換した上で,その平均値を計算する.
Y = (X - 100.0)/100.0
関数での処理はデータの終端を表す「-1」を識別して処理を終了する.
関数の呼び出し前後で入力データを表示し,補正が行われていることが確認できるようにする.

2. 以下のエラーやトラブルに困っています。
warning C4473: 'scanf_s': 書式文字列として渡された引数が不足しています
note: プレースホルダーとそのパラメーターには 1 の可変個引数が必要ですが、0 が指定されています。
note: 不足している可変個引数 1 が書式文字列 '%lf' に必要です
warning C4473: 'printf': 書式文字列として渡された引数が不足しています
note: プレースホルダーとそのパラメーターには 1 の可変個引数が必要ですが、0 が指定されています。
note: 不足している可変個引数 1 が書式文字列 '%lf' に必要です
warning C4473: 'printf': 書式文字列として渡された引数が不足しています
note: プレースホルダーとそのパラメーターには 1 の可変個引数が必要ですが、0 が指定されています。
note: 不足している可変個引数 1 が書式文字列 '%lf' に必要です
warning C4473: 'printf': 書式文字列として渡された引数が不足しています
note: プレースホルダーとそのパラメーターには 1 の可変個引数が必要ですが、0 が指定されています。
note: 不足している可変個引数 1 が書式文字列 '%lf' に必要です
warning C4473: 'printf': 書式文字列として渡された引数が不足しています
note: プレースホルダーとそのパラメーターには 1 の可変個引数が必要ですが、0 が指定されています。
不足している可変個引数 1 が書式文字列 '%lf' に必要です
warning C4715: 'henkan2': 値を返さないコントロール パスがあります。
warning C4715: 'nyuuryoku2': 値を返さないコントロール パスがあります。
warning C4715: 'henkan1': 値を返さないコントロール パスがあります。

4. 自分は何が解らないのか、知りたいのか
プレースホルダーとそのパラメーターには 1 の可変個引数が必要ですが、0 が指定されていますの
不足している可変個引数 1 が書式文字列 '%lf' に必要です
'printf': 書式文字列として渡された引数が不足しています
値を返さないコントロール パスがあります。

などのエラーメッセージの意味と解消法を知りたい。

全体のプログラムの流れと根本的な間違いなど。

5. 今のCの知識はどの程度なのか
かなりの初心者

アバター
Hiragi(GKUTH)
記事: 167
登録日時: 13年前
住所: 大阪府
連絡を取る:

Re: 配列を関数に渡すプログラムについて

#4

投稿記事 by Hiragi(GKUTH) » 6年前

1. 10行目scanf_sの使い方が正しくありません。

コード:

scanf_s("書式指定子",&変数名);
2.同様にprintfの使い方が正しくありません。

コード:

printf("文字列や書式指定子",変数名);
3.10 12 14行目で使用しようとしている変数iは宣言されていません。
4.25 37 53 71行目のfor文の使い方がおかしいです。

コード:

for(初期化;条件式;再初期化式)
他にも大量におかしな点がありますがパット見の部分だけ、
今回のその問題は課題でしょうか?明らかに質問者様のレベルには難しい問題かと思われます。
関数分けされておりますが、どれもほとんど意味不明です。
だいがくせい!

Cstudent

Re: 配列を関数に渡すプログラムについて

#5

投稿記事 by Cstudent » 6年前

Hiragi(GKUTH) さんありがとうございます。
基本的なところを修正したのですが、値を返さないコントロール パスがあります。というエラーを直すには、根本的にプログラムをどうしたらいいでしょうか?
4つに関数分けしたのは、それぞれの関数内で、1つの戻り値を返せば出力したい4つの条件を実行できるとおもったからです。意味不明なことをいってたらすいません。

コード:

#include<stdio.h>
double nyuuryoku1(double d[],double X[],double Y[]);
double nyuuryoku2(double d[], double X[],double Y[]);
double henkan1(double d[], double X[], double Y[]);
double henkan2(double d[], double X[], double Y[]);
int main(void)
{  int i;
   double c,e,f,g;
	double d[9],X[9],Y[9];
printf("100か, ら200までの間の小数を入力してください(最大10故,-1で終了)\n");
scanf_s("%lf",&d[i]);
f = nyuuryoku1(d, X, Y);
printf("入力されたデータ:%lfです。\n",X[i]);
g= nyuuryoku2(d, X, Y);
printf("0-1間変換をかけたデータ: %lfです。yn",Y[i]);
c = henkan1(d,X,Y);
printf("入力されたデータの平均値は%lfです。\n",c);
e = henkan2(d,X,Y);
printf("変換をかけたデータの平均値は%lfです。\n",e);
		return 0;
}
double nyuuryoku1(double d[],double X[],double Y[]) 
{   
	int i;
	int s = 0;
	for (i = 0; i <= 9; i++) {
		if (d[i] == -1) {
			break;}
		else
		s = s + i;
		X[i] = d[i];                  		
	}return X[i];
} 
double nyuuryoku2(double d[], double X[], double Y[])
{
	int i;
	int s = 0;
	for (i = 0;i<=9; i++) {
		if (d[i] == -1) {
			break;}
		else
			s = s + i;
		X[i] = d[i];
		Y[i] = (X[i] - 100.0) / 100.0; return Y[i];
		return Y[i];
	}
}
double henkan1(double d[], double X[], double Y[])
{
	int i;
	int s = 0;
	double t;
	double average1;
	for (i = 0;i <= 9; i++) {
		if (d[i] == -1) {
			break;
		}
		else
			s = s + i;
		X[i] = d[i];
		Y[i] = (X[i] - 100.0) / 100.0; return Y[i];
		t = t + X[i];
		average1 = t / s;
		return average1;
	}
}
double henkan2(double d[], double X[], double Y[]) {
	int i;
	int s = 0;
	double n;
	double average2;
	for (i = 0; i <= 9; i++) {
		if (d[i] == -1) {
			break;}
		else
			s = s + i;
		X[i] = d[i];
		Y[i] = (X[i] - 100.0) / 100.0; return Y[i];
		n = n + Y[i];
		average2 = n / s;
		return average2;
	}
}

アバター
Hiragi(GKUTH)
記事: 167
登録日時: 13年前
住所: 大阪府
連絡を取る:

Re: 配列を関数に渡すプログラムについて

#6

投稿記事 by Hiragi(GKUTH) » 6年前

45 64 81行目のreturnは、もしd[0]が-1だった場合実行されないため、関数nyuuryoku2 henkan1 henkan2は値を返さず終了してしまいます。
いかなる場合も必ず値を返すように修正してください。
だいがくせい!

Cstudent

Re: 配列を関数に渡すプログラムについて

#7

投稿記事 by Cstudent » 6年前

Hiragi(GKUTH) さんが書きました:45 64 81行目のreturnは、もしd[0]が-1だった場合実行されないため、関数nyuuryoku2 henkan1 henkan2は値を返さず終了してしまいます。
いかなる場合も必ず値を返すように修正してください。
Hiragi(GKUTH)" さんありがとうございます。プログラムを修正してみました。

コード:

#include<stdio.h>
double nyuuryoku1(double d[],double X[],double Y[]);
double nyuuryoku2(double d[], double X[],double Y[]);
double henkan1(double d[], double X[], double Y[]);
double henkan2(double d[], double X[], double Y[]);
int main(void)
{  int i=0;
   double c,e,f,g;
	double d[9],X[9],Y[9];
printf("100か, ら200までの間の小数を入力してください(最大10故,-1で終了)\n");
scanf_s("%lf\n",&d[i]);
f = nyuuryoku1(d, X, Y);
printf("入力されたデータ:%lf \n",X[i]);
g= nyuuryoku2(d, X, Y);
printf("0-1間変換をかけたデータ: %lfです。yn",Y[i]);
c = henkan1(d,X,Y);
printf("入力されたデータの平均値は%lfです。\n",c);
e = henkan2(d,X,Y);
printf("変換をかけたデータの平均値は%lfです。\n",e);
		return 0;
}
double nyuuryoku1(double d[],double X[],double Y[]) 
{   
	int i=0;
	int s = 0;
	for (i = 0; i <= 9; i++) {
		if (d[i] == -1) {
			break;}
		else
		s = s + i;
		X[i] = d[i];                  		
	}return X[i];
} 
double nyuuryoku2(double d[], double X[], double Y[])
{
	int i=0;
	int s = 0;
	for (i = 0;i<=9; i++) {
		if (d[i] == -1) {
			break;}
		else
			s = s + i;
		X[i] = d[i];
		Y[i] = (X[i] - 100.0) / 100;
	}
	return Y[i];
		
}
double henkan1(double d[], double X[], double Y[])
{
	int i=0;
	int s = 0;
	double t=0;
	double average1;
	for (i = 0;i<= 9; i++) {
		if (d[i] == -1) {
			break;
		}
		else
			s = s + i;
		X[i] = d[i];
		Y[i] = (X[i] - 100.0) / 100.0; return Y[i];
		t = t + X[i];
	
	}average1 = t / s;
	return average1;
}
double henkan2(double d[], double X[], double Y[]) {
	int i=0;
	int s = 0;
	double n=0;
	double average2;
	for (i = 0; i<= 9; i++) {
		if (d[i] == -1) {
			break;}
		else
			s = s + i;
		X[i] = d[i];
		Y[i] = (X[i] - 100.0) / 100.0; 
		n = n + Y[i];
		
	}average2 = n / s;
	return average2;
}

ビルドエラーは、消えたのですが、デバックで、2つ目のデータ入力から先で計算が行われません。

100か, ら200までの間の小数を入力してください(最大10故,-1で終了)
125.0
130.5
入力されたデータ:125.000000
0-1間変換をかけたデータ: 0.250000です。yn入力されたデータの平均値は0.250000です。
変換をかけたデータの平均値は-185119262698635652374959525400921212517924320689708494487552.000000です。
続行するには何かキーを押してください . . .

この原因と修正方法が全く分からないので教えて下さい。

かずま

Re: 配列を関数に渡すプログラムについて

#8

投稿記事 by かずま » 6年前

Cstudent さんが書きました:ビルドエラーは、消えたのですが、デバックで、2つ目のデータ入力から先で計算が行われません。

100か, ら200までの間の小数を入力してください(最大10故,-1で終了)
"最大10故" ?
double d[9] ですから、入力データを入れる場所は 9個しかなく、
10個のデータと -1 を入れることはできません。
"最大 8個" とするか、double d[11] にしてください。

i は 0 ですから、d[0] に最初のデータが読み込まれます。
d[1]以降への読み込みはこのプログラムにはありません。
scanf の書式の "\n" には特別な意味があります。
それを理解しない限り使用しないでください。
Cstudent さんが書きました:この原因と修正方法が全く分からないので教えて下さい。
修正方法

コード:

    double d[11], X[11], Y[11];
    for (i = 0; i < 11; i++) {
        if (scanf_s("%lf", &d[i]) != 1) return 1;
        if (d[i] == -1) break;
    }
    if (i == 11) return 1;
他にもたくさん変なところがあります。
nyuuryoku1 の Y は何のためにあるんですか?
nyuuryoku1 の s は何のためにあるんですか?
return X; の X は -1 ですよね。
どういう意味があるんですか?

一行ごとに、これは何をしているのかをよく考えてコーディングしてください。
そして、実行したとしたら、各変数がどのように変化していくのかを確認してください。
プログラムを実行しなくても、紙と鉛筆があれば、値の変化を追えるはずです。

Cstudent

Re: 配列を関数に渡すプログラムについて

#9

投稿記事 by Cstudent » 6年前

返信遅くなり申し訳ありません。かずまさんありがとうございます。
ビルドエラーを直したのですが、根本的にプログラムがおかしく、目的の数値の出力と平均値の出力がどうしてもできないので、参考例を教えて下さい。よろしくお願いします。

かずま

Re: 配列を関数に渡すプログラムについて

#10

投稿記事 by かずま » 6年前

Cstudent さんが書きました:1. 自分が今作りたいプログラムの内容
キーボードから100から200までの数字(小数)を入力させ,入力された数値の平均値を表示する.
入力にはscanf_s関数を使い,-1が入力されるまで繰り返し入力を受け付ける.
平均値の計算には関数を用いる.
関数へのデータ渡しには配列を使い,平均値の受け取りには戻り値を使う.
関数では,100 ≦X ≦200 のデータを次式に従って 0 ≦Y ≦1 のデータに変換した上で,その平均値を計算する.
Y = (X - 100.0)/100.0
関数での処理はデータの終端を表す「-1」を識別して処理を終了する.
関数の呼び出し前後で入力データを表示し,補正が行われていることが確認できるようにする.
ここには、「入力データは最大 10個」というのがありませんが、最初の質問には
あったので、そういうことにしておきます。

「平均値の計算には関数を用いる」とありますが、
「入力に関数を用いる」というのはありません。

入力データの平均値と、変換後のデータの平均値を戻り値として返すなら、
関数が 2つ要ることになるのかな?と考えました。

ということで、次のようなプログラムを書いてみました。

コード:

#include <stdio.h>

double 平均(double X[])
{
    //自分で書いてください。
}

double 変換平均(double X[], double Y[])
{
    double sum = 0;
    int i;
    for (i = 0; X[i] != -1; i++) {
        Y[i] = (X[i] - 100.0) / 100.0;
        sum += Y[i];
    }
    Y[i] = -1;
    return sum / i;
}

int main(void)
{
    double X[11], Y[11], ave;

    printf("100.0 から 200.0 までの数を最大 10個入力してください\n");
    int i;
    for (i = 0; i < 11; i++) {
        scanf_s("%lf", &X[i]);
        if (X[i] == -1) break;
    }
    if (i == 11) { printf("入力が多すぎる\n"); return 1; }

    printf("入力されたデータ\n");
    for (int i = 0; X[i] != -1; i++)
        printf(" %g", X[i]);
    printf("\n");
    ave = 平均(X);
    printf("入力されたデータの平均値は %g です。\n", ave);

    ave = 変換平均(X, Y);
    printf("変換されたデータ\n");
    for (int i = 0; Y[i] != -1; i++)
        printf(" %g", Y[i]);
    printf("\n");
    printf("変換されたデータの平均値は %g です。\n", ave);

    return 0;
}
入力データの個数はチェックしていますが、値が 200を超えるとか、
数字ではない場合などのエラーチェックはしていません。

これを参考に、自分でプログラムを書いて貼り付けてください。
動いたから終わり、ではなく、すべての行の意味を理解してください。

Cstudent

Re: 配列を関数に渡すプログラムについて

#11

投稿記事 by Cstudent » 6年前

返信遅くなり申し訳ありません。かずまさん参考例を教えていただきありがとうございます。
プログラムが目的通りに動作してくれなかった原因
1.自作関数内で、数値の読み込み(scanf)をやろうとしたこと
2.関数内で、読み込んだ数値が-1出ない時にループを回すコードを書いていなかったこと
2.最後にmain関数で11個目の数値が読み込まれた時の処理のことを考えていなかったこと
3.無駄な引数を宣言していたこと
などがありました。

かずまさんの参考例を元にしながら、修正した点
1.main関数内で、数値の読み込みを行うようにする
2.関数内のforループは、読み込んだ数値が-1出ない時にループを回すようにする
3.main関数内で、11個目の数値が、読み込まれた時にどうするのかくこと。
4.無駄な引数は、消去したこと

プログラム(少し言葉を変えました)は、一応動きましたが、理解出来なかった点
1.

コード:

	if (i == 11) { printf("入力は最大10個までです。\n"); return 1; }
main関数内のループは、iが0から10までしか増えないと思うのですが、ループを抜けた後に、ifの条件でどうしてi==10ではなく、i==11になるのでしょうか? 実際にiが10でやると、数値の嵐になりました。
又、return 1というのは、どういった意味なのでしょうか? 戻り値で1を返しいることぐらいしか分かりません。

2.出力は%fに変えてしまったのですが、出力の%gの方がよいのでしょうか?
返信遅くなり申し訳ありません。かずまさん参考例を教えていただきありがとうございます。
プログラムが目的通りに動作してくれなかった原因
1.自作関数内で、数値の読み込み(scanf)をやろうとしたこと
2.関数内で、読み込んだ数値が-1出ない時にループを回すコードを書いていなかったこと
2.最後にmain関数で11個目の数値が読み込まれた時の処理のことを考えていなかったこと
3.無駄な引数を宣言していたこと
などがありました。

かずまさんの参考例を元にしながら、修正した点
1.main関数内で、数値の読み込みを行うようにする
2.関数内のforループは、読み込んだ数値が-1出ない時にループを回すようにする
3.main関数内で、11個目の数値が、読み込まれた時にどうするのかくこと。
4.無駄な引数は、消去したこと

プログラム(少し言葉を変えました)は、一応動きましたが、理解出来なかった点
1.

コード:

	if (i == 11) { printf("入力は最大10個までです。\n"); return 1; }
main関数内のループは、iが0から10までしか増えないと思うのですが、ループを抜けた後に、ifの条件でどうしてi==10ではなく、i==11になるのでしょうか? 実際にiが10でやると、数値の嵐になりました。
又、return 1というのは、どういった意味なのでしょうか? (数値が11個入力されたときに、戻り値の1をmainに返すという意味ですか?)

2.出力の変換指定は%fに変えてしまったのですが、出力の変換指定は%gの方がよいのでしょうか?
%fは、実数を出力し、%gは、実数を最適な形式で出力するとネットにかいてあったのですが、違いが良く分かりません。

まだまだ分かっておらず、申し訳ないのですが、教えて下さい。よろしくお願いします。
  
 

コード:

#include <stdio.h>

double 平均(double X[])
{
	double heikin = 0;
	int i;
	for (i = 0; X[i] != -1; i++) {

		heikin += X[i];
	}
	X[i] = -1;
	return heikin / i;
}

double 変換平均(double X[], double Y[])
{
	double sum = 0;
	int i;
	for (i = 0; X[i] != -1; i++) {
		Y[i] = (X[i] - 100.0) / 100.0;
		sum += Y[i];
	}
	Y[i] = -1;
	return sum / i;
}

int main(void)
{
	double X[11], Y[11], ave;

	printf("100.0 から 200.0 の間の小数を入力してください(最大10個,-1で終了)\n");
	int i;
	for (i = 0; i < 11; i++) {
		scanf_s("%lf", &X[i]);
		if (X[i] == -1) break;

	}
	if (i == 11) { printf("入力は最大10個までです。\n"); return 1; }

	printf("入力されたデータ:\n");
	for (int i = 0; X[i] != -1; i++)
		printf(" %f", X[i]);
	printf("\n");
	ave = 平均(X);
	printf("入力されたデータの平均値は %f です。\n", ave);

	ave = 変換平均(X, Y);
	printf("0-1間変数への変換をかけたデータ:\n");
	for (int i = 0; Y[i] != -1; i++)
		printf(" %f", Y[i]);
	printf("\n");
	printf("変換をかけたデータの平均値は %f です。\n", ave);

	return 0;
}
教えて下さい。よろしくお願いします。
  
 

コード:

#include <stdio.h>

double 平均(double X[])
{
	double heikin = 0;
	int i;
	for (i = 0; X[i] != -1; i++) {

		heikin += X[i];
	}
	X[i] = -1;
	return heikin / i;
}

double 変換平均(double X[], double Y[])
{
	double sum = 0;
	int i;
	for (i = 0; X[i] != -1; i++) {
		Y[i] = (X[i] - 100.0) / 100.0;
		sum += Y[i];
	}
	Y[i] = -1;
	return sum / i;
}

int main(void)
{
	double X[11], Y[11], ave;

	printf("100.0 から 200.0 の間の小数を入力してください(最大10個,-1で終了)\n");
	int i;
	for (i = 0; i < 11; i++) {
		scanf_s("%lf", &X[i]);
		if (X[i] == -1) break;

	}
	if (i == 11) { printf("入力は最大10個までです。\n"); return 1; }

	printf("入力されたデータ:\n");
	for (int i = 0; X[i] != -1; i++)
		printf(" %f", X[i]);
	printf("\n");
	ave = 平均(X);
	printf("入力されたデータの平均値は %f です。\n", ave);

	ave = 変換平均(X, Y);
	printf("0-1間変数への変換をかけたデータ:\n");
	for (int i = 0; Y[i] != -1; i++)
		printf(" %f", Y[i]);
	printf("\n");
	printf("変換をかけたデータの平均値は %f です。\n", ave);

	return 0;
}

かずま

Re: 配列を関数に渡すプログラムについて

#12

投稿記事 by かずま » 6年前

Cstudent さんが書きました: プログラム(少し言葉を変えました)は、一応動きましたが、理解出来なかった点
1.

コード:

	if (i == 11) { printf("入力は最大10個までです。\n"); return 1; }
main関数内のループは、iが0から10までしか増えないと思うのですが、ループを抜けた後に、ifの条件でどうしてi==10ではなく、i==11になるのでしょうか? 実際にiが10でやると、数値の嵐になりました。
又、return 1というのは、どういった意味なのでしょうか? (数値が11個入力されたときに、戻り値の1をmainに返すという意味ですか?)
i は、-1 でない入力データの個数を表しています。

-1 でない入力データが 10個までの正常な入力の場合、
i は 10までしか増えません。X に -1 を格納して
ループを抜けます。

-1 でない入力データが 11個続く異常な入力の場合、
i は 11 になって、ループを抜けます。X[0]~X[10] の
11個の要素には、-1 でない値が入っていて、-1 は
どこにもありません。

i が 11 の場合、異常な入力なので、return 1; で終了
させます。

i が 10 の時に、return 1; で終了させるようにすると、
-1 でない入力データが 10個で、そのあとに -1 のある
正常な入力を処理できなくなります。さらに、
-1 でない入力データが 11個の場合に、終了できず、
次に進み、-1 がないので、平均を求める関数内では
ループを終了できず、配列 X の範囲外を参照して、偶然
-1.0 が見つかるまで処理を続け、未定義動作となります。

main関数を終了するとき、正常終了なら 0 (または EXIT_SUCCESS)を
返し、異常終了なら それ以外を返すことが規格で決められています。

Cstudent さんが書きました: 2.出力の変換指定は%fに変えてしまったのですが、出力の変換指定は%gの方がよいのでしょうか?
%fは、実数を出力し、%gは、実数を最適な形式で出力するとネットにかいてあったので
すが、違いが良く分かりません。

コード:

#include <stdio.h>

int main(void)
{
    double a = 0.0000123456789, b = 12.345678900000, c = 1234567890000.0;

    printf(" %%f: %15f %15f %15f\n", a, b, c);
    printf(" %%e: %15e %15e %15e\n", a, b, c);
    printf(" %%g: %15g %15g %15g\n", a, b, c);
    return 0;
}
実行結果

コード:

 %f:        0.000012       12.345679 1234567890000.000000
 %e:    1.234568e-05    1.234568e+01    1.234568e+12
 %g:     1.23457e-05         12.3457     1.23457e+12
 
%f は、固定小数点形式(fixed format) ddd.ddd
%e は、指数形式(exponential format) d.ddde+dd
%g は、%f と %e の適切な方を選択(general format?)

固定小数点形式では、小さな値や、大きな値の表示が不適切です。
指数形式は、どんなに小さな値もどんなに大きな値も同じ形式で表示
しますが、理系の人ならともかく、一般の人にはなじみがありません。

今回の問題にはどれが適切だと思いますか?

かずま

Re: 配列を関数に渡すプログラムについて

#13

投稿記事 by かずま » 6年前

Cstudent さんが書きました:

コード:

double 平均(double X[])
{
    double heikin = 0;
    int i;
    for (i = 0; X[i] != -1; i++) {

        heikin += X[i];
    }
    X[i] = -1;
    return heikin / i;
}
X が -1 のときループを抜けたのに、
X に -1 を代入するのは変です。

平均値 = 総和 / 個数
なので、heikin という名前は変です。

Cstudent さんが書きました: プログラムが目的通りに動作してくれなかった原因
1.自作関数内で、数値の読み込み(scanf)をやろうとしたこと

数値の読み込みを main ではない関数でもできますよ。

コード:

#include <stdio.h>

int 入力(double X[])
{
    int i;
    for (i = 0; i < 11; i++) {
        if (scanf_s("%lf", &X[i]) != 1) return -1;
        if (X[i] == -1) break;
        if (X[i] < 100 || X[i] > 200) return -1;
    }
    return i;
}

void 出力(double X[])
{
    for (int i = 0; X[i] != -1; i++)
        printf(" %g", X[i]);
    printf("\n");
}

double 平均(double X[])
{
    double sum = 0;
    int i;
    for (i = 0; X[i] != -1; i++)
        sum += X[i];
    return sum / i;
}
 
double 変換平均(double X[], double Y[])
{
    double sum = 0;
    int i;
    for (i = 0; X[i] != -1; i++)
        sum += Y[i] = (X[i] - 100.0) / 100.0;
    Y[i] = -1;
    return sum / i;
}
 
int main(void)
{
    double X[11], Y[11], ave;
 
    printf("100.0 から 200.0 の間の小数を入力してください(最大10個,-1で終了)\n");
    switch (入力(X)) {
    case -1: printf("入力エラーです。\n"); return 1;
    case 0:  printf("入力がありません。\n"); return 2;
    case 11: printf("入力は最大10個までです。\n"); return 3;
    }
    printf("入力されたデータ:\n");
    出力(X);
    printf("入力されたデータの平均値は %g です。\n", 平均(X));
 
    ave = 変換平均(X, Y);
    printf("0-1間変数への変換をかけたデータ:\n");
    出力(Y);
    printf("変換をかけたデータの平均値は %g です。\n", ave);
 
    return 0;
}

返信

“C言語何でも質問掲示板” へ戻る