txtファイルを読み込んで配列に格納、計算、出力する

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ゆめゆめ
記事: 1
登録日時: 1年前

txtファイルを読み込んで配列に格納、計算、出力する

#1

投稿記事 by ゆめゆめ » 1年前

初めての投稿なので不手際がありましたらすみません。C言語もプログラミングも初学者です。
Windows で Visual Studio、Developer Command Promptを使用しています。

91 63 78
67 72 46
...
上記のような10行3列で点数が書かれたテキストファイル2つを読み込み、2つのファイルの和の合計点、合計点の行ごとの和の総点、総点の最大・最小値、を算出して画面とファイルに出力する課題が出されたのですが、エラーメッセージも出ず、表示もファイル出力も何も起こらない状態になってしまい困っています。

コード:

#include <stdio.h>
#define NUM 10
FILE *fin1, *fin2, *fout;

int main(void)
{
	int i = 0, j = 0, a[NUM][3], b[NUM][3], total[NUM][3], all[NUM];


	fin1 = fopen("i-data1.txt", "r");
	if (fin1 = NULL){
		printf("File not open\n");
		return 1;
	}
	for (i = 0; i < NUM; i++) {
		fscanf(fin1, "%d %d %d", &a[i][0], &a[i][1], &a[i][2]);
	}
	
	fin2 = fopen("i-data2.txt", "r");
	if (fin2 = NULL){
		printf("File not open\n");
		return 1;
	}
	for (i = 0; i < NUM; i++) {
		fscanf(fin2, "%d %d %d", &b[i][0], &b[i][1], &b[i][2]);
	}


	fout = fopen("o-data.txt", "w");
	if (fout == NULL) {
		printf("File not open\n");
		return 1;
	}
	
	// 合計点を計算
	for (i = 0; i < NUM; i++){
		for (j = 0; j <= 2; j++){
			total[i][j] = a[i][j] + b[i][j];
		}
	}
	
	// 総点を計算
	for (i = 0; i < NUM; i++){
		all[i] = total[i][0] + total[i][1] + total[i][2];
	}
	
	// 最高総点、最低総点を求める
	int max = all[0], min = all[0];
	for (i = 1; i <= NUM; i++){
		if (max < all[i])
			max = all[i];
		if (min > all[i])
			min = all[i];
	}
	
	// 画面に出力
	printf("合計点         総点\n");
	for (i = 0; i < NUM; i++){
		for (j = 0; j <= 2; j++){
			printf("%4d", total[i][j]);
		}
		printf("%6d\n", all[i]);
	}
	printf("\n");
	printf("最高総点 = %d, 最低総点 = %d", max, min);
	
	
	// ファイルo-data.txtに出力
	fprintf(fout, "合計点         総点\n");
	for (i = 0; i < NUM; i++){
		for (j = 0; j <= 2; j++){
			fprintf(fout, "%4d", total[i][j]);
		}
		fprintf(fout, "%6d\n", all[i]);
	}
	fprintf(fout, "\n");
	fprintf(fout, "最高総点 = %d, 最低総点 = %d\n", max, min);


	fclose(fin1);
	fclose(fin2);
	fclose(fout);
	
	return 0;
}
教科書に多次元配列の表示方法が載っておらず授業でも説明もされずでよくわかっていないのですが、使うように指示されているので雰囲気で書きました、、、本当に初心者なので駄質問かもしれませんがご回答よろしくお願いいたします。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: txtファイルを読み込んで配列に格納、計算、出力する

#2

投稿記事 by みけCAT » 1年前

少なくとも以下の行が間違っています。

コード:

if (fin1 = NULL){
if (fin2 = NULL){
C言語において、= は代入演算子であり、fin1 や fin2 の値が NULL に設定されてしまいます。
そして、代入後の値である NULL に評価されます。
これは偽とみなされるので、チェックに引っかからず、ファイルポインタが NULL のまま処理が進んでしまい、強制終了の原因となります。
fout と同様に、比較演算子の == を用いるべきです。

コード:

for (i = 1; i <= NUM; i++){
配列 all は 0~(NUM-1) の NUM 要素しかないので、all[NUM] にアクセスしてはいけません。
条件を i < NUM とするべきです。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: txtファイルを読み込んで配列に格納、計算、出力する

#3

投稿記事 by みけCAT » 1年前

また、通常の処理では致命的になる可能性は低いですが、少なくとも以下の行が不適切です。

コード:

FILE *fin1, *fin2, *fout;
一般に、無駄にグローバル変数を使うべきではないとされています。
今回の場合、
・ポインタ3個だけなので、十分に小さいデータである可能性が高く、スタックに置いてもスタックオーバーフローを起こす可能性は十分低い
・main 関数でしか使用されない
ため、グローバル変数ではなく main 関数のローカル変数にするべきでしょう。

コード:

fscanf(fin1, "%d %d %d", &a[i][0], &a[i][1], &a[i][2]);
fscanf(fin2, "%d %d %d", &b[i][0], &b[i][1], &b[i][2]);
fscanf 関数は、読み込んで変数に格納したデータの数を返します。
(または、最初の読み込みの前に入力エラーが起きた場合、EOF を返します)
fscanf の戻り値は無視せず、期待する数のデータを読み込めたかをチェックするべきです。
さもないと、データの読み込みに失敗していてもデータを読み込んだと思い込んだまま処理を進め、未初期化の変数の値が処理に使われ、予期せぬ結果になる可能性があります。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

返信

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