はじめまして、数ヶ月前からC言語を始めたものです。
ファイルからのデータ読み込みについて質問です。
テキストファイルとして以下のようなものがあります。
*************************
23 3346 45 423 34
23 345 45 56 6345
・・・
・・・
*************************
このようなファイルから読み込みを行って、スペース毎の数字(整数型)を構造体の中の変数に順次格納していくようなプログラムを作りたいとおもうのですがどのように行ったらいいのでしょうか?
現在、fgets()で行ごとの文字列を読み込んでから、型変換を行おうと心みているのですが、うまくいきません。
回答よろしくお願いします。
A 回答 (4件)
- 最新から表示
- 回答順に表示
No.4
- 回答日時:
・サンプル1(直接読み込み)
#include<stdio.h>
…
int a[5];
FILE *fp;
…
while(fscanf(fp,"%d%d%d%d%d",&a[0],&a[1],&a[2],&a[3],&a[4]) != EOF){
代入処理
}
scanfは空白や改行文字で、数の区切りを見つけ、自動的にスキップしてくれます。
・サンプル2(fgetsを用いる場合)
#include<stdio.h>
…
int a[5];
FILE *fp;
char buf[256];
…
while(fgets(buf,sizeof(buf),fp) != NULL){
sscanf(buf,"%d%d%d%d%d",&a[0],&a[1],&a[2],&a[3],&a[4],&a[5]);
代入処理
}
sscanfを用いて、文字列から各数字を読み取ります。
・サンプル3(1文字ずつ入力)
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
…
int c;
int i,a[5],counter;
char buf[32];
FILE *fp;
…
counter = 0;
while(1){
while(!isgraph((c = fgetc(fp))) && c != EOF){
/*区切り文字のスキップ*/
;
}
if(c == EOF)
break;
i=0;
do{
buf[i++] = c;
}while(isdigit((c = fgetc(fp))));
buf[i] = '\0';
a[counter++] = atoi(buf);
if(counter>=5){
counter=0;
代入処理
}
if(c==EOF)
break;
}
1文字ずつ読み込んで、処理していきます。
fgetsだと領域の大きさがデータに対して少なすぎると、数字が途切れてしまう可能性があります。
極端な例ですと、fgets(buf,8,fp)に対し、「44 28 312…」などです。
そのため、fgetsは確実に行入力するとは限らないことに注意しておかないといけません。
isdigitではなく、isgraphを用いたのは、負の整数の場合に'-'も読み取るようにするためです。数字と'-'だけと判断すればよいのですが、ここでは妥協しました。
1行の個数が固定でない場合は、if(counter>=5)をif(c=='\n')とすれば、対応することが出来ます。ですが、配列の大きさを超えないようにチェックする記述も必要となります。
あと、ちょっとしたことですがfgetcの返り値はint型で受け取るべきであることを忘れないように。
分からない関数があれば、調べてみてください。標準関数なので、探せば色々見つかると思います。
初めは慣れないやり方や記述があるでしょうが頑張ってくださいね。長くなり読みづらそうですみません。
丁寧な解説ありがとうございました。
おかげで、プログラムを完成させることができました。
複数のやり方を教えていただいたことはとても勉強になりました。これからもプログラミングの勉強をがんばっていきたいとおもいます。また何かありましたらよろしくお願いします。
本当にありがとうございました。
No.3
- 回答日時:
★回答者 No.1 です。
修正と新しい回答です。・前回のサンプルの『fgets』の第3引数は『stdin』は『fp』が正しく、
『scanf』は『fscanf』にすべきでした。つまり、
『while ( fgets(buff,sizeof(buff),fp) != NULL ){』と
『fscanf( fp, "%d %d %d %d %d\n", &a, &b, &c, &d, &e );』が
正しい修正版です。申し訳ありません。→『fp』がファイルポインタです。
・akoyagai さん、ご指摘ありがとうございます。
別の回答:
・今度は、1行のデータが5つ以外の場合です。→最大 100 の要素に対応。
・文字列を左から順番に解読して、数字文字列を整数値に変換します。
・下にサンプルを載せます。→ポインタを使っていますよ。
サンプル:
int pos, num[ 100 ]; ←要素数
char buff[ 256 ];
char *seek; ←ポインタです。
(オープン処理)
:
while ( fgets(buff,sizeof(buff),fp) != NULL ){ ←1行ずつ読み込む
for ( pos = 0, seek = buff ; *seek != '\0' ; pos++ ){ ←文字列を左から右へ解読する
while ( isspace(*seek) ){ ←空白文字をスキップ
seek++;
}
if ( pos >= 100 ){ ←データ要素が 100 を越えたので強制的にループを抜ける
break;
}
num[ pos ] = atoi( seek ); ←数字文字列を整数に変換する(英字の場合は 0 をセット)
while ( !isspace(*seek) && (*seek != '\0') ){ ←空白文字以外をスキップ(数字,英字,記号など)
seek++;
}
}
data.array[ 0 ] = num[ 0 ]; // data が構造体、array[] がメンバです
data.array[ 1 ] = num[ 1 ]; // num が1行のデータ要素(1-100)です
data.array[ 2 ] = num[ 2 ];
data.array[ 3 ] = num[ 3 ];
data.array[ 4 ] = num[ 4 ];
}
:
(クローズ処理)
最後に:
・上記のサンプルの『fp』がファイル・ポインタです。
・『isspace』を使うために『#include <ctype.h>』をインクルードして下さい。
・『atoi』関数を使うために『#include <stdlib.h>』もインクルードして下さい。
・サンプル・ソースを紹介しましたが、構造体メンバがはっきりしないので正確なアドバイスなどは
これ以上で来ません。あくまで参考として下さい。
・以上。おわり。
丁寧な説明ありがとうございました。
おかげでプログラムを完成させることができました。
ひとつのやり方だけでなく、別のやり方でのやり方を教えていただいたことは、よい勉強になりました。これからも、プログラミングをがんばっていきます。
本当にありがとうございました。
No.2
- 回答日時:
5つ数字があると決まっている場合は、ファイルポインタをfpとすると、
fscanf(fp,"%d %d %d %d %d\n",&a[0],&a[1],&a[2],&a[3],&a[4]);
という感じで、後はNo.1の方のようにすればいいと思います。
(No.1の方は標準入力からの入力と勘違いされている気がします)
また、そうと決まっていない場合でも、
char temp[10];
//一時的に確保します
char c;
//getcの格納先
int a[100];
//数字の格納先
memset(temp,0,sizeof(temp));
//初期化
int i=0,j=0;
//iはtempが何文字あるか、jはaがどの要素まで格納されているか
whlie((c=getc(fp))!=EOF){
//ファイルの終わりまできたら終了
if((c!=' ')&&(c!='\n')){
//スペースや改行で無いのならtempにcを足していきます
temp[i]=c;
i++;
}
else{
//スペースや改行なら、そこでtempを数字の型に変換します
a[j]=atoi(temp);
memset(temp,0,sizeof(temp));
i=0;
//初期化です
j++;
//aの次の要素に格納できるように
}
}
実際に試してはいませんが、たぶんいけると思います。(ごめんなさい、見にくかも)
もし、うまくいかないとか、説明の意味がわからないとかがあれば、また尋ねてください。
丁寧な説明ありがとうございました。
おかげでプログラムが完成しました。
ひとつのやり方だけでなく別のやり方も教えていただき、理解が深まったと思います。
また何かあったらよろしくお願いします。
本当に助かりました、ありがとうございます。
No.1
- 回答日時:
★『scanf』関数で簡単に出来ると思います。
・1行のデータが必ず5つの数字があるの場合は、
『scanf( "%d %d %d %d %d\n", &a, &b, &c, &d, &e );』で簡単に型変換できると思います。
これで、『a』~『e』の変数を構造体にセットするか、直接構造体メンバを『scanf』の引数に
アドレス指定で渡します。
サンプル:
char buff[ 256 ];
int a, b, c, d, e;
(オープン処理)
:
while ( fgets(buff,sizeof(buff),stdin) != NULL ){
scanf( "%d %d %d %d %d\n", &a, &b, &c, &d, &e );
data.array[ 0 ] = a; // data が構造体、array[] がメンバです
data.array[ 1 ] = b;
data.array[ 2 ] = c;
data.array[ 3 ] = d;
data.array[ 4 ] = e;
}
:
(クローズ処理)
最後に:
・1行のデータが5つ以外の場合は、文字列を左から右へサーチして数字を整数値に変換します。
・文字列を整数に変換するには『atoi』関数を使います。また、文字列のサーチ移動はポインタを
使うと簡単ですが、C言語を始めたばかりならば『添え字』を使った方法でも良いでしょう。
・まずは C言語での『文字列とは』を理解しましょう。C言語では char 型の配列で文字列を表現
して、最後は必ず NULL 文字をセットします。この NULL 文字が文字列の終端を表します。
・以上。おわり。→上記はエラーチェックは省略しています。
参考URL:http://www9.plala.or.jp/sgwr-t/c/sec05.html
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
複数ファイルの同時読み込みの...
-
C言語 csv 配列
-
日本語ファイル名のFTPについて
-
fopenでファイル名に、変数を使...
-
大量の入力ファイルを扱うとき...
-
テキストファイル内に対して, ...
-
C言語でセグメンテーションエ...
-
C言語のファイル入出力の問題です
-
C言語でファイル読み書きを早く...
-
C言語 BUF_SIZE文字以上ある行...
-
ADボードのデータの遅れについて
-
c言語でのfscanfについて
-
write関数でファイルディスクリ...
-
ファイル結合
-
テキストファイルをバイナリフ...
-
行毎の黒のドット(ピクセル)...
-
ファイルが読み込めない・・・
-
C言語 初心者です。
-
c言語による画像処理について
-
エラー C2664
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
c言語でのfscanfについて
-
ファイルへの書込み処理が異常...
-
C言語でファイル読み書きを早く...
-
エラーがわかりません、、
-
日本語ファイル名のFTPについて
-
fopenでファイル名に、変数を使...
-
ファイル出力で改行を入れたい!
-
テキストファイル内に対して, ...
-
複数ファイルの同時読み込みの...
-
C言語の課題です
-
C言語を用いて、csvファイル内...
-
バイナリファイルの読み込み(C...
-
C言語にてXMLファイルから任意...
-
ファイルが読み込めない・・・
-
構造体のメンバにファイルポイ...
-
CRC32の計算方法
-
ファイルからCR/LFを除去したい
-
C言語におけるファイル読み込み...
-
C言語 csv 配列
-
エラー C2664
おすすめ情報