ファイルから読み込んだ値を配列に格納し,出力する

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

ファイルから読み込んだ値を配列に格納し,出力する

#1

投稿記事 by シオリ » 9年前

はじめまして
プログラム初心者でわからないことがあり,投稿させていただきました.
現在,数値が1列に約1000個並んだファイルがあり,それを読み込んだのち,
行数を固定した配列(例えば行は220個,列は定めずにファイルの読み込みが終了するまで)に格納したいと考えています.
1行n列のものを220行m列にするといったイメージです.
そして220行m列となった状態で,別のファイルに書き出したいと考えています.
現段階でここまで書いていますが,出力されずに悩んでいます.
iやj,mやn等,自分で設定しておきながらあまりわかっていません.
このような者ですがなにか助言していただけませんか?
よろしくお願いします.

コード:

#include <stdio.h>

int main (void)
{
	int m,n,i,j;
	double height[220][500];
	FILE *text1,*text2;

	text1=fopen("imput.txt","r");
	printf("読み込みファイルオープン成功\n");

	if(text1==NULL)
	{
		printf("ファイルがありません\n");
		return -1;
	}

	text2=fopen("output.txt","w");
	printf("書き出しファイルオープン成功\n");

	if(text2==NULL)
	{
		printf("ファイルがありません\n");
		return -1;
	}


	(fscanf(text1,"%lf",&height[220][500])!=EOF);

	for(i=0; i<m; i++)
	{
		for(j=0; j<n; j++)
		{
			fprintf(text2,"%8.2f\n",height[i][j]);
		}
	}

	fclose(text2);
	fclose(text1);
	return 0;
}

かずま

Re: ファイルから読み込んだ値を配列に格納し,出力する

#2

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

適当に書いてみましたが、未完成で、ちょっと問題があります。
220 や 5 というのは、#define を使って書き換えるべきでしょう。
また、goto を使ってしまいましたが、これの是非を考えるべきでしょう。
テストが不十分です。データの個数が次の場合どうなるか、報告してください。
個数: 0, 1, 219, 220, 221, 1000, 1099, 1100, 1101
そうして、あなたのプログラムを完成し、ここに提示した後、解決にしましょう。

コード:

#include <stdio.h>

int main(void)
{
    int m, n, i, j;
    double buf[220][5];
    FILE *text1, *text2;

    text1 = fopen("input.txt", "r");
    if (text1 == NULL) { printf("input file error\n"); return 1; }
    text2 = fopen("output.txt", "w");
    if (text2 == NULL) { printf("output file error\n"); return 2; }

    for (m = 0; m < 5; m++)
        for (n = 0; n < 220; n++)
            if (fscanf(text1, "%lf", &buf[n][m]) != 1) goto out;
    if (m == 5) { printf("too many data\n"); return 3; }
out:
    for (i = 0; i < n; i++) {
        for (j = 0; j <= m; j++)
            fprintf(text2, " %g", buf[i][j]);
        fprintf(text2, "\n");
    }
    for (i = n; i < 220; i++) {
        for (j = 0; j < m; j++)
            fprintf(text2, " %g", buf[i][j]);
        fprintf(text2, "\n");
    }

    fclose(text2);
    fclose(text1);
    return 0;
}
Linux か cygwin を使っている場合、seq 1000 >input.txt で入力ファイルが作れますよ。

シオリ
記事: 7
登録日時: 9年前

Re: ファイルから読み込んだ値を配列に格納し,出力する

#3

投稿記事 by シオリ » 9年前

お返事ありがとうございます.
以下のように書き換え(defineを使ってみました),実行してみました.
実際にファイルに出力されるようになりましたが,2行目からimputデータと値が異なります.
また,input.txtに1199個のデータがあるのに対してoutput.txtでは26400個も出てしまいました.

コード:

#include <stdio.h>
#define row 10
#define sequence 220 


int main (void)
{
	int m,n,i,j;
	double buf[sequence][row];
	FILE *text1,*text2;

	text1=fopen("dem.txt","r");
	printf("読み込みファイルオープン成功\n");

	if(text1==NULL)
	{
		printf("ファイルがありません\n");
		return -1;
	}

	text2=fopen("output.txt","w");
	printf("書き出しファイルオープン成功\n");

	if(text2==NULL)
	{
		printf("ファイルがありません\n");
		return -1;
	}

	for(m=0; m<sequence; m++)
	{
		for(n=0; n<row; n++)
		{
			if(fscanf(text1,"%lf",&buf[n][m])!=1) goto out;
			if(m==sequence)
			{	
				printf("too many data\n");
				return -1;
			}
		}
	}	

out:
	for(i=0; i<n; i++)
	{
		for(j=0; j<m; j++)
		{
			fprintf(text2,"%8.2f",buf[i][j]);
			fprintf(text2,"\n");
		}
	}
	 
	for (i = n; i < sequence; i++)
    {
		for (j = 0; j < m; j++)
        {
			fprintf(text2, " %8.2f", buf[i][j]);
			fprintf(text2, "\n");
		}
	}

	fclose(text2);
	fclose(text1);
	return 0;
}

シオリ
記事: 7
登録日時: 9年前

Re: ファイルから読み込んだ値を配列に格納し,出力する

#4

投稿記事 by シオリ » 9年前

12行目のdem.txtはinput.txtの間違いです

かずま

Re: ファイルから読み込んだ値を配列に格納し,出力する

#5

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

シオリ さんが書きました: 以下のように書き換え(defineを使ってみました),実行してみました.
実際にファイルに出力されるようになりましたが,2行目からimputデータと値が異なります.
また,input.txtに1199個のデータがあるのに対してoutput.txtでは26400個も出てしまいました.
間違いは、
  • row と sequence を混同している
  • for文の次の文を for文の中に押し込んでいる
  • 出力の for文が 2つあるのは、列の長さが違うためなのに j < m と同じにしている

コード:

#include <stdio.h>
#define row 220                             // 10 --> 220
#define sequence 10                         // 220 --> 10
 
 
int main (void)
{
    int m,n,i,j;
    double buf[row][sequence];              // buf[sequence][row] -->
    FILE *text1,*text2;
 
    text1=fopen("input.txt","r");           // "dem.txt" --> "input.txt"
    printf("読み込みファイルオープン成功\n");

    if(text1==NULL)
    {
        printf("ファイルがありません\n");
        return -1;
    }
 
    text2=fopen("output.txt","w");
    printf("書き出しファイルオープン成功\n");

    if(text2==NULL)
    {
        printf("ファイルがありません\n");
        return -1;
    }
 
    for(m=0; m<sequence; m++)
    {
        for(n=0; n<row; n++)
        {
            if(fscanf(text1,"%lf",&buf[n][m])!=1) goto out;
        }
    }   
    if(m==sequence)                         // #
    {                                       // #
        printf("too many data\n");          // #
        return -1;                          // #
    }                                       // #

out:
    for(i=0; i<n; i++)
    {
        for(j=0; j<=m; j++)                 // j<m --> j<=m
        {
            fprintf(text2," %8.2f",buf[i][j]);   // "%8.2f" --> " %8.2f"
        }
        fprintf(text2,"\n");                // #
    }
     
    for (i = n; i < row; i++)               // sequence --> row
    {
        for (j = 0; j < m; j++)
        {
            fprintf(text2, " %8.2f", buf[i][j]);
        }
        fprintf(text2, "\n");               // #
    }
 
    fclose(text2);
    fclose(text1);
    return 0;
}
ファイルオープン失敗の場合も、常に
ファイルオープン成功と出力するのはいかがなもんでしょうか?

複数のデータによる確認をお願いします。

さて、元のプログラムから goto をなくすと次のようになります。
出力もひとつにまとめてみました。

コード:

#include <stdio.h>

#define ROW 220
#define COL 5

int main(void)
{
    int m, n, i, j;
    double buf[ROW][COL];
    FILE *text1, *text2;

    text1 = fopen("input.txt", "r");
    if (text1 == NULL) { printf("input file error\n"); return 1; }
    text2 = fopen("output.txt", "w");
    if (text2 == NULL) { printf("output file error\n"); return 2; }

    for (m = 0; m < COL; m++) {
        for (n = 0; n < ROW; n++)
            if (fscanf(text1, "%lf", &buf[n][m]) != 1) break;
        if (n < ROW) break;
    }
    if (m == COL) { printf("too many data\n"); return 3; }
    for (i = 0; i < ROW; i++) {
        if (i == n) m--;
        for (j = 0; j <= m; j++)
            fprintf(text2, " %8g", buf[i][j]);
        fprintf(text2, "\n");
    }

    fclose(text2);
    fclose(text1);
    return 0;
}

シオリ
記事: 7
登録日時: 9年前

Re: ファイルから読み込んだ値を配列に格納し,出力する

#6

投稿記事 by シオリ » 9年前

ありがとうございます.
指摘してくださったところについてはきちんと理解し,改善することができました.
input.txtにあるデータの個数が10個,40個,120個の場合を試しましたが,
全て同じようにoutput.txtにも出力されていました.
また,ファイルオープン失敗の際に成功と出力されないようにもしました.

コード:

#include <stdio.h>
#define ROW 220
#define COL 5


int main (void)
{
	int m,n,i,j;
	double buf[ROW][COL];
	FILE *text1,*text2;

	text1=fopen("input.txt","r");

	if(text1==NULL)
	{
		printf("読み込みファイルがありません\n");
		return -1;
	}

	text2=fopen("output.txt","w");

	if(text2==NULL)
	{
		printf("書き出しファイルがありません\n");
		return -1;
	}

	for(m=0; m<=COL; m++)
	{
		for(n=0; n<=ROW; n++)
		{
			if(fscanf(text1,"%lf",&buf[n][m])!=1) break;
		}	
		if(n < ROW) break;
	}
	
	if(m==COL)
	{	
		printf("too many data\n");
		return -1;
	}
		
	for(i=0; i<ROW; i++)
	{
		if(i == n){m--;}

		for(j=0; j<=m; j++)
		{
			fprintf(text2,"%8.2f",buf[i][j]);
		}
		fprintf(text2,"\n");
	}

	fclose(text2);
	fclose(text1);
	return 0;
}

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

Re: ファイルから読み込んだ値を配列に格納し,出力する

#7

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

シオリ さんが書きました:

コード:

	double buf[ROW][COL];
/* 略 */
	for(m=0; m<=COL; m++)
	{
		for(n=0; n<=ROW; n++)
		{
			if(fscanf(text1,"%lf",&buf[n][m])!=1) break;
		}	
		if(n < ROW) break;
	}
確保された領域の範囲外にアクセスする可能性があり、危険です。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

かずま

Re: ファイルから読み込んだ値を配列に格納し,出力する

#8

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

シオリ さんが書きました:input.txtにあるデータの個数が10個,40個,120個の場合を試しましたが,
全て同じようにoutput.txtにも出力されていました.
if(i == n){m--;} を if (i == n && --m <= 0) break; に修正してください。
あとは、みけCATさんの指摘に従い、m<=COL を m < COLになどしてください。

かずま

Re: ファイルから読み込んだ値を配列に格納し,出力する

#9

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

かずま さんが書きました:if(i == n){m--;} を if (i == n && --m <= 0) break; に修正してください。
間違えました。
if(i == n){m--;} を if (i == n && --m < 0) break; に修正してください。

シオリ
記事: 7
登録日時: 9年前

Re: ファイルから読み込んだ値を配列に格納し,出力する

#10

投稿記事 by シオリ » 9年前

以下のように変更しました.

コード:

#include <stdio.h>
#define ROW 220
#define COL 5


int main (void)
{
	int m,n,i,j;
	double buf[ROW][COL];
	FILE *text1,*text2;

	text1=fopen("input.txt","r");

	if(text1==NULL)
	{
		printf("読み込みファイルがありません\n");
		return -1;
	}

	text2=fopen("output.txt","w");

	if(text2==NULL)
	{
		printf("書き出しファイルがありません\n");
		return -1;
	}

	for(m=0; m<COL; m++)
	{
		for(n=0; n<ROW; n++)
		{
			if(fscanf(text1,"%lf",&buf[n][m])!=1) break;
		}	
		if(n < ROW) break;
	}
	
	if(m==COL)
	{	
		printf("too many data\n");
		return -1;
	}
		
	for(i=0; i<ROW; i++)
	{
		if(i == n && --m < 0)break;

		for(j=0; j<=m; j++)
		{
			fprintf(text2,"%8.2f",buf[i][j]);
		}
		fprintf(text2,"\n");
	}

	fclose(text2);
	fclose(text1);
	return 0;
}
また,行列に格納したのち,その行列のまま出力するにはどのようにすればよいですか?
現在は1列のまま出力されているので,n行m列のように表示させたいです.

かずま

Re: ファイルから読み込んだ値を配列に格納し,出力する

#11

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

シオリ さんが書きました: また,行列に格納したのち,その行列のまま出力するにはどのようにすればよいですか?
現在は1列のまま出力されているので,n行m列のように表示させたいです.
入力データは、何個ですか?

入力データが 220個の場合は、220行 1列になります。

入力データが 1000個の場合は、220行 5列になります。ただし、
最初の 120行は 5列ですが、121~220行目は 4列になります。
1000 = 220 x 4 + 120 = 120 x 5 + 100 x 4 だから当然です。

シオリ
記事: 7
登録日時: 9年前

Re: ファイルから読み込んだ値を配列に格納し,出力する

#12

投稿記事 by シオリ » 9年前

かずま さんが書きました:
シオリ さんが書きました: また,行列に格納したのち,その行列のまま出力するにはどのようにすればよいですか?
現在は1列のまま出力されているので,n行m列のように表示させたいです.
入力データは、何個ですか?

入力データが 220個の場合は、220行 1列になります。

入力データが 1000個の場合は、220行 5列になります。ただし、
最初の 120行は 5列ですが、121~220行目は 4列になります。
1000 = 220 x 4 + 120 = 120 x 5 + 100 x 4 だから当然です。
失礼しました,私の勘違いです.
220行n列ではなく,n行220列と表示させたかったのでした.

シオリ
記事: 7
登録日時: 9年前

Re: ファイルから読み込んだ値を配列に格納し,出力する

#13

投稿記事 by シオリ » 9年前

また,データを縦に並べるのではなく,スペースで区切り,横に並べていきたいのですがどのようにすればよいですか?
1 2 3 4 5 … 220
221 222 223 …
このように並べていきたいです.

閉鎖

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