- ベストアンサー
C言語でテキストファイルを読み込んで配列に格納する方法
- C言語でテキストファイルを読み込む方法と、1行目の文字列を表示し、2行目以降を配列に格納する方法を解説します。
- テキストファイルの読み込みは、ファイルを開いて行ごとに読み込んでいく方法が一般的です。
- 1行目の文字列を表示するには、最初にファイルを開いて1行目を読み込み、表示します。2行目以降の数値を配列に格納する場合は、ループを使って行ごとに読み込み、配列に追加します。
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
もうひとつのファイルを特定した場合の回答例です。 malloc()は、読み込み行毎に行うことはせず、ファイルサイズから導き出されるのがこのプログラムの特徴です。 また、読み込まれた data[][]は、通常の配列書式でそのまま使えるので、従来のプログラムがそのまま生かされます。 /* 実行は ./×××.exe データファイル または ./a.out データファイル */ #include <stdio.h> /* printf(), fopen(), fgets(), fscanf() */ #include <stdlib.h> /* exit(), malloc() */ #include <string.h> /* strlen() */ #include <errno.h> /* errno */ #define RETU 3 /* 3列 */ #define SIZE 256 #define SAFTY 3 /* もしも */ int main(int argc, char *argv[]) { FILE *fp; char *file_name, comment[SIZE]; int (*dat)[RETU], line_size, n_gyo, i=0; /* 1)ファイル名を特定 */ if(argc!=2){ fprintf(stderr, "Parameter error.\n"); exit(EXIT_FAILURE); } file_name=argv[--argc]; /* 2)ファイルを開く */ if( (fp=fopen(file_name,"r")) == NULL){ fprintf(stderr, "%s\n", strerror(errno)); exit(EXIT_FAILURE); } /* 3)1行の大きさとその行数から、配列を動的に割り当て. */ fgets(comment, SIZE, fp); line_size = strlen(fgets(comment, SIZE, fp)); fseek(fp, 0, SEEK_END); n_gyo = ftell(fp) / line_size + SAFTY; if((dat = (int (*)[RETU])malloc(n_gyo * sizeof(*dat))) == NULL){ fprintf(stderr, "%s\n", strerror(errno)); exit(EXIT_FAILURE); } fseek(fp, 0, SEEK_SET); /* 4)最初の文字列をまとめて読み込み、まとめて表示する */ fgets(comment, SIZE, fp); printf("%s", comment); /* 5)ファイルの終わりまで配列を読み込み、その都度表示する */ while(fscanf(fp,"%d %d %d", &dat[i][0], &dat[i][1], &dat[i][2])!=EOF){ printf("%6d %6d %6d\n", dat[i][0], dat[i][1], dat[i][2]); i++; } /* 6)ファイルを閉じる */ fclose(fp); /* 7)malloc()後のメモリ解法を忘れぬこと */ free(dat); return 0; }
その他の回答 (6)
- 和泉 博(@hiroshi09s)
- ベストアンサー率54% (59/109)
>ファイルを読み込み、1行目の文字列を表示し、2行目以降を読み込んでn行3列の配列に入れ更に表示したい > >ファイル1 50行3列 >ファイル2 100行3列 >・・・ >などと、nはファイル別に固定の値をとります。 あちらのサイトでも答えておきましたが、ファイル名が異なり、n行も変わるとのことですが、100行×3列×整数4バイト=1200バイトと1.2kバイトほどのメモリ消費に過ぎないので、現在の1Gバイトメモリーの時代を配慮すれば、200行(2.4kバイト)ほどの容量を確保されてはいかがでしょう。最大行のファイルに合わせればOKかと。 プログラムはファイル名が変わることが前提のようですから、ファイル名を特定しないリダイレクトを念頭に置いた標準入出力パスを意識した UNIX的なプログラムが良いように思います。 実行は ↓です。 ./a.out<ファイル名 あるいは ./a.out<ファイル名 2>/dev/null 意味ないけど cat は何らかの処理プログラムのつもり ./a.out<ファイル名 2>/dev/null | cat #include <stdio.h> /* printf(), fscanf() */ #include <stdlib.h> /* exit() */ #define N 200 /* 配列の大きさ */ #define SIZE 256 int main(void) { char comment[SIZE]; int dat[N][3], i=0; /* 1)最初の文字列をまとめて読み込み、まとめて表示する */ fgets(comment, SIZE, stdin); fprintf(stderr, "%s", comment); //計算に必要のない場合、出力しないようにする /* 2)ファイルの終わりまで配列を読み込み、その都度表示する */ while(fscanf(stdin,"%d %d %d", &dat[i][0], &dat[i][1], &dat[i][2])!=EOF){ fprintf(stdout, "%6d %6d %6d\n", dat[i][0], dat[i][1], dat[i][2]); if(++i>N){ /* ただし、サイズN 以内 (読み込んだ行はカウントされ、残される)*/ fprintf(stderr, "Memory overflow.\n"); //エラー表示は標準エラー出力パスへ exit(EXIT_FAILURE); } } return 0; }
- Tacosan
- ベストアンサー率23% (3656/15482)
「nはファイル別に固定の値をとります」とありますが, この「n」は外から与えられるものなのですか? それとも, プログラムが自分で調べなければならないものですか? 前者なら malloc から読み込み, 後者なら大きさを先に調べて malloc か必要になる都度 realloc.
- hanabutako
- ベストアンサー率54% (492/895)
おっと、nが可変でしたね。 先のプログラムでもC99をサポートしていればMAX_ROWSをコマンド引数で渡すと出来るのですが、そういう事をしないとしたらこうですね。 #include <err.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_LINE 1024 #define NUM_COLS 3 void show_array(char* label[NUM_COLS], int **array, int num_rows) { int i, j; printf("\narray: \n"); for (i = 0; i < NUM_COLS; i++) printf("%s\t", label[i]); printf("\n"); for (i = 0; i < num_rows; i++) { for (j = 0; j < NUM_COLS; j++) { printf("%d\t", array[i][j]); } printf("\n"); } } int main(int argc, char *argv[]) { FILE *fp; char line[MAX_LINE]; char* label[NUM_COLS]; int **array = NULL; int row; if (argc != 2) errx(-1, "strange argument"); fp = fopen(argv[1], "r"); if (fp == NULL) err(errno, "fopen failed %s", argv[1]); for (row = -1; fgets(line, sizeof(line), fp) != NULL;) { char *token, *string; int col; line[strlen(line) - 1] = '\0'; /* remove '\n' */ if (line[0] == '\0') /* skip a blank line */ continue; if (row != -1) { /* allocate memory for a new row */ array = realloc(array, sizeof(array[0]) * (row + 1)); if (array == NULL) err(errno, "realloc"); array[row] = malloc(sizeof(int) * NUM_COLS); if (array[row] == NULL) err(errno, "malloc"); } for (col = 0, string = line; (token = strsep(&string, " \t")) != NULL;) { /* skip the blank */ if (*token == '\0') continue; if (col >= NUM_COLS) errx(-1, "the number of columns is larger than expected: %d @ line %d", col, row); if (row == -1) { label[col] = strdup(token); if (label[col] == NULL) err(errno, "strdup"); } else array[row][col] = atoi(token); printf("%s\t", token); col++; } if (col != NUM_COLS) errx(-1, "the number of columns is not enough: %d @ line %d", col, row); printf("\n"); row++; } fclose(fp); show_array(label, array, row); /* free the array */ while (--row > -1) free(array[row]); free(array); return EXIT_SUCCESS; }
- hanabutako
- ベストアンサー率54% (492/895)
何かの課題っぽい感じもしますが、プログラミングは誰かが書いたプログラムを見るだけでも勉強になると思いますので一応書いてみます。 #include <err.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_LINE 1024 #define NUM_ROWS 3 #define NUM_COLS 3 void show_matrix(char* label[NUM_COLS], int matrix[NUM_ROWS][NUM_COLS]) { int i, j; printf("\nmatrix: \n"); for (i = 0; i < NUM_COLS; i++) printf("%s\t", label[i]); printf("\n"); for (i = 0; i < NUM_ROWS; i++) { for (j = 0; j < NUM_COLS; j++) { printf("%d\t", matrix[i][j]); } printf("\n"); } } int main(int argc, char *argv[]) { FILE *fp; char line[MAX_LINE]; char* label[NUM_COLS]; int matrix[NUM_ROWS][NUM_COLS]; int row, col; if (argc != 2) errx(-1, "strange argument"); fp = fopen(argv[1], "r"); if (fp == NULL) err(errno, "fopen failed %s", argv[1]); for (row = -1; row < NUM_ROWS; row++) { char *token, *string; if (fgets(line, sizeof(line), fp) == NULL) err(errno, "fgets failed: %d", row); line[strlen(line) - 1] = '\0'; /* remove '\n' */ string = line; col = 0; while ((token = strsep(&string, " \t")) != NULL) { if (col >= NUM_COLS) errx(-1, "the number of columns is larger than expected: %d @ line %d", col, row); if (row == -1) { label[col] = strdup(token); if (label[col] == NULL) err(errno, "strdup"); } else matrix[row][col] = atoi(token); printf("%s\t", token); col++; } if (col != NUM_COLS) errx(-1, "the number of columns is not enough: %d @ line %d", col, row); printf("\n"); } show_matrix(label, matrix); fclose(fp); return EXIT_SUCCESS; } 自分が課題の出題者なら質問サイトはチェックしますけどね。
- asuncion
- ベストアンサー率33% (2127/6289)
n行3列のnは固定ですか?可変ですか?
- SaKaKashi
- ベストアンサー率24% (755/3136)
ファイルを開く 1行読む 表示する 1行読む ファイルの終わりかどうか判定して、終わりなら終了 読んだ値を配列に入れる 一行読む 3行前にもどる
補足
ファイル1 50行3列 ファイル2 100行3列 ・・・ などと、nはファイル別に固定の値をとります。