C言語で改行までの一文字ずつのファイル読み込みプログラムを作成する方法

このQ&Aのポイント
  • C言語で現在ある入力ファイルを読み込んで計算し、ファイルを出力するプログラムを作成中です。
  • ファイルを読み込む際に、改行までの値を一文字ずつ読み込むという作業を行いたいです。
  • しかし、現在のコードでセグメント例外が発生し、強制終了してしまいます。解決策を教えていただきたいです。
回答を見る
  • ベストアンサー

改行までの一文字ずつのファイル読み込み

こんにちは。 C言語で現在ある入力ファイルを読み込んで計算し、 ファイルを出力するというプログラムを作成中なのですが、 ファイルを読み込む場合に、 改行までの値を一文字ずつ読み込むという作業をさせたいと思っています。 データは、 abc defgh ijk ..... といった感じで入力されており、 while((c = fgetc(fp)) != '\n'){ fscanf(fp, "%c", &q[i]); } と書いたのですが、セグメント例外が出て強制終了してしまいます。 初歩的なことで申し訳ないのですが、教えていただきたいと思います。よろしくおねがいします。

質問者が選んだベストアンサー

  • ベストアンサー
  • qwertyf
  • ベストアンサー率51% (14/27)
回答No.5

(1)fgetc() の時点でもう既に1文字データを読んでいるので、 fscanf() で'再度取得'することはできません。 q[i] には c の値をそのまま代入してください。 (2)i はインクリメントしなくてよいのでしょうか? (3)行の終端 '\n' を検出して while を抜けた後、 printf 文などでそのまま表示させていませんか? 文字列 q[] の終端にヌル文字を入れる必要があります。 (q[]が予めゼロクリアされているのなら入れる必要はありません) (4)それと、feof() でファイル終端をチェックしながらやった方がいいです。 オーバーフローを起こさない為に q[] には大きめの配列を確保してください。 char q[1024]; int i = 0, c; while( !feof( fp ) ) {   if( ( c = fgetc( fp ) ) == '\n' )     break;   q[i++] = c; } q[i++] = '0'; みたいな感じ。

pooh_bear
質問者

補足

データの書き方が悪かったのですが、 実際のデータ自体は、いろいろな種類があって、 pqrs 01 p qs q q r qr r s p s 0 p p qs のようになっています。 一行の空行ごとにデータの種類が違うので、それによって読み込み方や、メモリを変えなければならないのです。(最後まで同じやり方でデータを読み込むのではなく、途中から途中まで。)なので、eof()の判定を使えないのではないかと 思います。 また、メモリ自体も動的に確保しなければならないので、もうちょっと変えなければなりませんよね。 やってみます。

その他の回答 (5)

  • qwertyf
  • ベストアンサー率51% (14/27)
回答No.6

#5です。 最後の行 q[i++] = '\0'; の間違いです。 スミマセン…

pooh_bear
質問者

お礼

この場を借りて・・・。 試行錯誤の結果、出来ました。ありがとうございました。 一番参考にさせていただいた方にポイントを差し上げます。

回答No.4

長さが全くわからないバッファの場合は、malloc で多めに確保するのが普通ですが、reallco() で際割り当てすることも出来ます。 #include <stdlib.h> char *a = 0; int sizeNow = 0; if (sizeNow が小さすぎる) { sizeNow += 10; // など、siezeNow を更新 realloc(a, sizeNow); } こんな感じで、再割り当てが出来ます。

pooh_bear
質問者

お礼

malloc, callocについては知っていましたが、reallocというものがあることは知りませんでした。 うまく使えたら良いなと思います。

回答No.3

こんにちは。 ファイルから1文字ずつ読み込むとい事ですが、書かれたプログラムでは、1つ飛ばしに読んでしまします。 セグメント例外といううことですが、fscanfの読み込み使われている配列変数qにアクセスするためのインデックス番号、iがqの容量を超えてしまったか、iが不定のために起こっていると思われます。 以下にサンプルを示します。サンプル中のLENは環境に合わせて変更してください。 #define LEN 80 char q[LEN+1]; i=0; while((c = fgetc(fp)) != '\n') q[i++] = c; if(i == LEN ) break; } q[i] = NULL;

pooh_bear
質問者

補足

No.1の方の補足にも書いたのですが、メモリは動的に取らなければならないので、LENを使って値を決め打ちすることはできないのです。 mallocやcallocで確保する方法をやってみたのですが、それも失敗してしまったので・・・。 もう少しトライしてみます。

noname#30727
noname#30727
回答No.2

運が悪いと、全部の'\n'をfscanfで取得してしまい、その後もEOFを取得し続ける事になりそうですね。 c = fgetc(fp)で取得したcを使うようにする。 改行までという条件は、'\n'またはEOFを取得するまでと読み替えた方が安全です。よってcはintで宣言する事になります。

pooh_bear
質問者

補足

cはintで宣言してました。 ご指摘ありがとうございます。

  • buihyaku
  • ベストアンサー率29% (97/326)
回答No.1

他の方が詳細なソースを示してくれるとおもいますので基本的なところだけ。。 fgetcで1文字読みしたときにファイルポインタは次の文字に進んでいるので、fscanfではその次の文字を読み込んでしまいます。 つまりfgetcで1文字、fscanfでもう1文字の2文字読んでいることになるため、q[]で用意したバッファサイズを超えてしまっているのではないでしょうか。

pooh_bear
質問者

補足

早速のご回答ありがとうございます。 どうやらそのようです。 動的に領域を確保せよとのことだったので、始めに個数を数えてからq[n]のnの部分に数字を入れることは可能なのでしょうか。

関連するQ&A

  • ファイル入力

    下記のようにテキストファイルをオープンして、fscanf文でデータを入力していくのですが、 ファイルの数が1000個ほどありまして、 ファイル名が abc001.txt abc002.txt abc003.txt ・ ・ abc100.txt のように一部だけ変わっているだけなんです。 すべてのファイル名を何回も記述するのはめんどうなので、簡単に出来る方法がありましたら、教えて欲しいです。 if((fp = fopen("abc001.txt","r"))!=NULL) { while(fscanf(fp,"%lf,%lf\n",&index[n][0],&index[n][1])!=EOF) ・ ・ ・ ・

  • ファイル出力で改行を入れたい!

    data.txtにファイル出力を行うのですが、gets(c)で入力した一語一語に改行を入れてdata.txtに出力したいのですがどうすればよいでしょうか。 返答のほどよろしくお願いいたします。 include<stdio.h> #define SIZE 20 void main(void) { char c[SIZE], *p; FILE *fp; fp = fopen("data.txt","w+"); p = c; while(gets(c) != NULL){ fputs(p,fp); } fclose(fp); printf("data.txtへ出力しました\n"); }

  • ファイルから一文字ずつ読み込む

    ファイルを読み込むfgetc()関数のところでプログラムが停止します。 以下が実行したプログラムです。 #include<stdio.h> void get_name(char name[],int a){ printf("ファイル名を入力してください。\n"); scanf("%s",name); } void open(FILE *fp2,char name[]){ if((fp2=fopen(name,"r"))==NULL){ printf("ファイルオープンエラー"); } } int count(FILE *fp3){ int ch=0; int count=0; if(fp3==NULL){ printf("error"); } while((ch=fgetc(fp3))!=EOF){ if(ch=='\n'){ count++; } } printf("TEST"); fclose(fp3); return(count); } int main (void){ FILE *fp; char fname[30]; get_name(fname,30); open(fp,fname); printf("%d",count(fp)); return(0);} ファイル名を入力してください。ファイル名を入力、プログラム停止です。 '\n'を数えれるようにしてください。御指摘お願いします。

  • fscanf関数について

    -------------------------------------------------- #include<stdio.h> #include<stdlib.h> int main() { FILE*fp; int ch,dt; char ss[80]; if((fp=fopen("bbb.txt","w"))==NULL){ printf("出力ファイルをオープンできません.\n"); exit(1); } fprintf(fp,"%c",'A'); fprintf(fp,"%s\n","abcdeABCDE"); fprintf(fp,"%d\n",1234); fclose(fp); if((fp=fopen("bbb.txt","r"))==NULL){ printf("入力ファイルをオープンできません.\n"); exit(1); } ch=fgetc(fp); printf("ch=%c\n",ch); fscanf(fp,"%s",ss); printf("ss=%s\n",ss); fscanf(fp,"%d",&dt); printf("dt=%d\n",dt); fclose(fp); return 0; } -------------------------------------------------- 以上のプログラムで、プログラムの通り「bbb.txt」は、 AabcdeABCDE 1234 となっております。 そこで疑問なのですが、「ch=fgetc(fp);」は1文字読み込みなので、'A'だけと分かるのですが、「fscanf(fp,"%s",ss);」はfpからの読み込みで何故、 AabcdeABCDE 1234 の全部を読み込まず、'A'を抜かした、「abcdeABCDE」だけを読み込んでくれるのか? 後、「fscanf(fp,"%d",&dt);」は何故「AabcdeABCDE」を抜かした、「1234」だけを読み込んでくれるのかが分かりません。 「fscanf(fp,"%d",&dt);」については数値だけを読み込んでくれるのかと思い、 ch=fgetc(fp); printf("ch=%c\n",ch); fscanf(fp,"%s",ss); printf("ss=%s\n",ss); の部分を無くせば、「1234」だけを読み込んでくれるのかと思ったのですが、数値は正しく表示されません。 以上教えていただければ嬉しいです。

  • 大文字を小文字に変換するプログラム

    if((fp4 = fopen("sample.txt","r")) == NULL){ printf("can't open\n"); return(-1);//強制終了 } else{ while((c=fgetc(fp4))!=EOF){/*EOFまでfp4に入力*/ if(isupper(c)){ c=tolower(c); printf("%s",c); } else printf("a"); //確認用 } } ファイルから文字を読み込んでctype関数を使って大文字から小文字に変換したいんですがうまくいきません。 コンパイルしても確認用が反応しないんでおそらくどこか間違ってると思うんですがわかりません。 ご教授宜しくお願いします。

  • ファイル内の文字列を配列へ

    テキストファイルの中の文字列を1字づつ配列に入れたいのですが、どのように書けばよいでしょうか? while((c=fgetc(fp)) ! = EOF){ c=rv[i];   i++; } 一応このようにやってみたのですが、ダメなようです。

  • C言語、fgetcを利用しファイルの内容を変数に

    C言語について質問です C言語のfgetcを利用しファイルの内容を変数にいれてそれを返す関数を作っているのですがうまくいきません <!--以下ソース--> char *file_get_contents(char *filename){ FILE *fp; int c; char *return_str; if((fp=fopen(filename,"r"))==NULL) return NULL; while((c=fgetc(fp))!=EOF ){ sprintf(return_str,"%c",c); } fclose(fp); return return_str; } 誰か理由と改善方法を教えてください!

  • ファイル操作

    あるファイルから長さの違った数字や文字を読み込んで配列に格納したいのですが数字などの長さが違うとなんかおかしくなってしまいます; 例えば 1 a 1 2 a 2 3 b 3 4 b 4 などのファイルはできるのですが 0 1 2 3 a 3 4 b 4 5 c 5 の場合5つの配列に格納したいのです。1行目で1つ2行目で1つ3行目の 左、真ん中、右の数字でそれぞれ1つづつ格納したいのです。 それで自分でやったのですが typedef struct path{ int left [100]; int right[100]; char center [100]; }Path; int main(int argc,char *argv[]) { FILE *fp; Path path; int i=0; int first; int second[100]; fp = fopen(argv[1],"r"); while(fscanf(fp,"%d %c %d",&path.left[i],&path.center[i],&path.right[i])==3){ i++; } fclose(fp); このようにやると3行目からはきちんとよみこむのですが1、2行目がうまくできません@@; firstとsecondのそれぞれ1、2行目を入れたいのです。 fscanfをもう1つ増やすしてもやってみましたがうまくいきませんでした。 ちなみにfscanf関数のところをならったばかりです。 fgetcとかそのようなのを使うのでしょうか?(よくわからないですけど) よろしくお願いします。ちなみにLinuxでgcc、C言語です。

  • ファイルから読み取った改行文字を消す方法

    C言語のプログラムから、テキストファイルを読み込むと、改行文字が・になってしまい、なんだか汚くみえてしまいます。 なので、ファイルから読み取った改行文字を消す方法が知りたいです。教えて下さい。

  • 複雑なファイルの読み取り

    あるファイルからある文字と数字を読み取りたいのですがうまくいきません。 ファイル(例) A01 B02 C03 A02 B01 A03 B03 C05 A04 C04 というファイルを読み込ませ、2行目のようにCがなければ1つ前の行のCをBがなければ1つ前のBをつかうようにしたいのですが、どうしたらいいのかわかりません。 ちなみに初心者ですので本を見ながら下記のようなところまで作ってみました。 データを検索して数値を入力 printf("A,B,Cの順で入力してください(大文字で)--"); gets(search1); gets(search2); gets(search3); while (1){ fseek(fp,RECORDLEN * no++,SEEK_SET); if(fscanf(fp,"%s",b) == EOF) break; if(strstr(b,search1) != NULL){ find++; fscanf(fp,"%s",e); fscanf(fp,"%s",d); printf("A=%s\n",b); printf("B=%s\n",e); printf("C=%s\n",d); } } いまの状態で検索すると最後の行などではBのところにCが入ったりします。どうすればうまくいくでしょうか。どなたか回答のほうをよろしくお願いします。

専門家に質問してみよう