• 締切済み

小数が、18行x72列、並んでいるファイルを読みます。どうしたら良いでしょうか。

・小数が、72列18行あります。 ・小数は、ときに負号が記載されていることがあります。 ・小数は、C言語でfprintfで、"%-7.5f " で打ち出したもので、見てみると、7桁、時に八桁のようですが。 ・区切りは、上記のように空白一つで、fprintfで書き出したはずなのですが、実際には、スペースが一つか二つ(不定。どうやら負号のない場合には空白が一つ増える・・・ということみたいですが不明)入っています。 ・72列のデータの後はすぐに改行しておらず、スペースが一つか二つはいって、改行しています。 自分で書き出したデータなのに間抜けなことですが、どうしたらC言語で安定して、読み込めるでしょうか。 fgets? fgetc? scanfは不安です。 windows2002, thinkpad, borland C v5.5無料版です。 どうぞよろしくお願いいたします。

みんなの回答

  • toysmith
  • ベストアンサー率37% (570/1525)
回答No.7

多分「初心者」に対する認識の違いかと… > 「きちんと理解させて、正しく使わせる」が良いでしょう。 きちんと理解できている人を「初心者」だとは思えないので、「初心者には禁止」と表現しています。 「わかんないならわかるまで使うな!」という意味合いです。 > バッファオーバフローを起こすって点が問題ですね バッファオーバーフローの危険をはらむプログラムは安定動作を期待できない。よって、「不安定なプログラム」と表現しています。 ソースコード的には「危険を含む」ですが、「プログラム(あいまいですね。作成されるソフトウェアと言う意味です)は不安定」だと。

全文を見る
すると、全ての回答が全文表示されます。
noname#205142
noname#205142
回答No.6

>> scanf("%s", s)のような使い方をしているから不安定なプログラムが出来上がるわけです。 >この使い方は安定してますよね。 安定か不安定かの問題ではなくて、バッファオーバフローを起こすって点が問題ですね。正しいく安全に使うにはバッファのサイズに合わせてフォーマットを指定する必要があります。 char buff[512]; scanf("%511s", s);

harapeko99
質問者

お礼

ありがとうございます。

全文を見る
すると、全ての回答が全文表示されます。
  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.5

当の質問者は、別のやり方に関心が移っている様子なので、回答に反応してみよう。 > 私的には「scanf系は初心者に使わせるべきではない」と思っています。 お互いにプロのようなので、その立場から。 私たちが初心者に対する態度として、「使わせるべきではない」ではなく、 「きちんと理解させて、正しく使わせる」が良いでしょう。 # 一生、初心者のままで良い、と割り切っている人を除いて 規格とは何か、エラーの扱いは々考えて、どう処理すべきか、ということを 考えるには、良い題材だと思います。 規格で決められている範疇を過ぎると、次には、WindowsAPI だとか システムコールだとか の世界に入ってゆくわけですから。 ちなみに、 > scanf("%s", s)のような使い方をしているから不安定なプログラムが出来上がるわけです。 この使い方は安定してますよね。駄目なのは、こういうやつでしょ? #include <stdio.h> int main(void) { int x; while (1) { printf("> "); scanf("%d", &x); /* 整数以外を入れると… */ if (x == 0) break; } return 0; }

harapeko99
質問者

お礼

ありがとうございます。

全文を見る
すると、全ての回答が全文表示されます。
  • toysmith
  • ベストアンサー率37% (570/1525)
回答No.4

scanf系関数に関して「初心者向け解説書が安易にscanfを使いすぎている」というのが最大の問題です。 「エラーチェック」や「正しい書式指定」という解説を一切行わず、scanf("%s", s)のような使い方をしているから不安定なプログラムが出来上がるわけです。 また、「scanfは処理系依存部分が多い」と言うことを言及している入門者はほとんどありません。 私的には「scanf系は初心者に使わせるべきではない」と思っています。 ただ、この質問の仕様なら#3の回答がベターでしょう。 考慮すべき点として ・1行が512バイト夫超える可能性があるなら確認が必要 前述のようにscanf系(printf系も)の関数は処理系依存部分が多いため「最低でも512バイトは処理できる」という仕様になっています。 実際の最大入力可能バイト数はコンパイラのマニュアルを参照してください。 ・エラーチェックが必要な場合 エラーチェックの質にもよりますが、細かくチェックする必要があるならstrtofを使いましょう。

harapeko99
質問者

お礼

ありがとうございます。

全文を見る
すると、全ての回答が全文表示されます。
  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.3

> 自分で書き出したデータなのに間抜けなことですが、どうしたらC言語で安定して、読み込めるでしょうか。 > > fgets? fgetc? scanfは不安です。 何が不安ですか? fscanf() を使うのが簡単で安定しています。 ただ数値を抜き出すだけならば、こんな感じ。fscanf() が空白や改行を読み飛ばしてくれます。   ※ No.2 と比べれば、どれだけ簡単に書けるかは一目瞭然ですね #include <stdio.h> int main(void) { FILE* in; double x; in = fopen("データファイル", "r"); while (fscanf(in, "%lf", &x) == 1) { printf("%f\n", x); } return 0; } scanf() や fscanf() は悪者扱いをされることが多いですが、きちんと知らない 人が、理由もわからずに、口伝に中途半端な知識が広がったのでしょう。 scanf() 系が苦手なのは、期待している書式と違うものがきたときの処置です。 先の例だと、実数とみなせない文字列(整数はOK)が来た場合には、あっさり ループを抜けます。 ただ、今回の場合には、自分で作成したデータということなので、その問題は 少ないと思います。

harapeko99
質問者

お礼

ありがとうございます。

全文を見る
すると、全ての回答が全文表示されます。
  • muyoshid
  • ベストアンサー率72% (230/318)
回答No.2

こんにちわ。 #1 のmuyoshid です。 > strtok(), strpbrk() 等で分割すれば良いと思います。 についてですが、strpbrk() は関係なかったようです。 失礼しました。 試しにサンプルプログラムを作ってみましたので、参考に してみて下さい。 但し、以下の注意点があります。 1) 空白とタブ文字を区切り文字としています。  → 変更がある場合は、SPLIT_CHAR を変更して下さい。 2) 1行の文字数は256文字まで (改行やNULL 文字を含めて)   として下さい。  → 変更がある場合は、BUF_SZ を変更して下さい。 3) 今回は特に数値への変換は行っていません。  → 必要に応じて、atof() 等で対応して下さい。 [以下、サンプルです] ------------------------------------------------- #include <stdio.h> #include <string.h> #include <stdlib.h> #define SPLIT_CHAR  "\t " #define BUF_SZ    256 static void get_data(FILE *); static void split_data(char *); void main() {  FILE *rfp;  rfp = fopen("data.txt", "r");  if (((FILE *)NULL) == rfp) {   printf("data file cannot open.\n");   exit(1);  }  get_data(rfp);  fclose(rfp);  exit(0); } static void get_data(FILE *rfp) {  char buff[BUF_SZ];  int  line;  line = 0;  while(!feof(rfp)) {   buff[0] = '\0';   fgets(buff, BUF_SZ, rfp);   line++;   printf("Line %d : %s", line, buff);   split_data(buff);  }  return; } static void split_data(char *str) {  char *sp;  sp = strtok(str, SPLIT_CHAR);  if (((char *)NULL) == sp) {   return;  }  printf("data : %s\n", sp);  for (;;) {   sp = strtok(NULL, SPLIT_CHAR);   if (((char *)NULL) == sp) {    break;   }   printf("data : %s\n", sp);  }  return; }

harapeko99
質問者

お礼

ありがとうございます。参考とするべきコードまでお示してくださって、嬉しいです。

全文を見る
すると、全ての回答が全文表示されます。
  • muyoshid
  • ベストアンサー率72% (230/318)
回答No.1

こんにちわ。 ファイルからデータの取り出し方ですが、 fgets() で1行データを取り出して、取り出したデータを strtok(), strpbrk() 等で分割すれば良いと思います。 1) 18行 と言う事を前提にせず、「while(!feof(rfp))」   で、ファイルの終わりまで読み込む。 2) 72列と言う事を前提にせず、空白, タブコード等で   区切られているデータを最後まで取り出す。 と言うようにされる事をお奨めします。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • fgetsを使って入力した文字列を読み込む。

    こんにちは。私は30代の男性です。 上司から、「C言語でコーディングする際にscanfは使わずにfgetsを使うように」との指示があったのですが、scanfしか使ったことがないので、具体的にどうコーディングすればいいのかわかりませんでした(聞いても教えてもくれず…)。どのようにすればfgetsを使って入力した文字列を読み取れるのか、わかる方がいらっしゃれば簡単な例文で教えて頂けるとありがたいのですが。 どうぞ宜しくお願い致します。

  • 文字列の読み込みに関して

    C言語で、fgetsを使って文字列ファイルから読み込みを行うと、改行もしくは指定した文字列が来ると読み込みを、止めますが途中で改行が来ても読み飛ばして。(丸)までを読み込むようにするには、どのようなコードを書けばいいのですか? 別に使う関数は、これ以外でもいいのでコードを教えてもらえますか? お願いします。

  • C言語の入出力関数の違い

    C言語を勉強しています。 自分が知っている入出力を行う関数は printf scanf fprintf fscanf sprintf sscanf gets puts getc putc fgets fputs fgetc fputc なのですがそれぞれのメリット・デメリットの違いがまだあいまいです。 というかまだ上の4つくらいしかまともに使ったことがありません。 自分の考えでは、 ・上の4つは書式を指定でき、ファイルから読み込みするときなどは fgetsよりもfscanfが使いやすいと思っています。 ・スペースを読み込みたいときはscanfではなくgetsを使わなければならない。 ・システム開発でscanfを使うことは危険なのでほとんどない。 間違った考え方をしていたり、どのようなデータのときに どの関数を使うのが正しい、常識、と知っている方いらっしゃいましたら 教えてください。

  • 標準入力の際に、、、fgets

    標準入力の際にgetsやscanfは読み込むバイト数を指定できないので危険、 fgetsを使えという話を良く聞きますが、fgetsだと改行まで読み込んで しまいますよね。これで少し困っています。 読み込んだ文字列から'\n'を探して'\0'を代入することはできますが 面倒くさいです。もっと手軽にscanfのように改行を含めずに 標準入力から受け付けるのをfgetsなどではどうやればいいのでしょうか。 よろしくお願いいたします。

  • 小数点を整数型に変換

    ・8.7  ・14.5 ・3.456 などのデータがあり、この値を四捨五入 などをせずに 「整数2桁 + 小数5桁」に変換したいのですが、String.Formatなどで行うと意図した値になりません。 ・8.7 ⇒ 87.00000 ・14.5 ⇒ 14.50000 ・3.456 ⇒ 34.56000 何か良い方法がありましたら、アドバイスを頂けないでしょうか。 言語:C# VisualStudio 2008 以上、よろしくお願い致します。

  • 文字列変換マクロ

    小数点以下5桁(B列)をC列に文字列として変換したいです。 (B列は3.62%入力で表示形式をパーセンテージの小数点以下5桁で表示) データ量が多いためVBA作成希望です。どなたか教示お願いします。

  • 文字列で小数点以下の0を削除したい

    「0.987000」とか「12.345670」などのように 小数点6桁目まで0埋めされた入力データがあります。 これの右の0を取った文字列を作成したいのですが 数値の誤差なく取る方法はあるでしょうか? 思いついたのは、「CDblしてCStrする。」です。

  • cシェルで指定行の文字列加工について

    cシェルで指定行の文字列加工について cシェルについて、以下のような加工をしたいのですがうまくいきません。 どなたか教えてください。 (1)1行目をMAX20byteになるように残りスペース埋め 最終行をMAX20byteになるように残りスペース埋め  A,000,000,000,000(改行)  ・(改行)  ・(改行)  ・(改行)  C,000,000(改行)        ↓  A,000,000,000,000 (改行)  ・(改行)  ・(改行)  ・(改行)  C,000,000 (改行) (2)1行目をMAX17byteになるように後半のスペースを削除   最終行を9byteになるように後半のスペースを削除   A,000,000,000,000 (改行)  ・(改行)  ・(改行)  ・(改行)  C,000,000 (改行)    ↓  A,000,000,000,000(改行)  ・(改行)  ・(改行)  ・(改行)  C,000,000(改行) すみませんが、よろしくお願いします(>_<)

  • ファイル読み込みについて

    CまたはC++で、データごとにタブで区切られたテキストファイルを読み込む処理があります。 例) 項目1(タブ)fea 5310 a(タブ)2009(改行) 項目2(タブ)dc 6307(タブ)2012(改行) 項目3(タブ)beaf 23 t(タブ)2010(改行) fscanf で読み込もうとしたのですが、タブとスペースが同じように扱われてしまうようで、 スペースが含まれるデータがある場合、上手く読み込めませんでした。 結局、fgets で一行ずつ一時バッファに読み込んでから一文字ずつチェックして データごとに切り分けたのですが、釈然としません。 もっと簡潔な方法はないでしょうか?

  • 小数の表示が・・・。

    初歩的な質問で申し訳ないです。 「2個の整数値を標準入力装置(キーボード)から読み込み、その平均値を計算して結果を標準出力装置(ディスプレイ)に出力するというプログラムを書きなさい。小数以下1桁を表示すること。」 という問題を考えていたのですが、上手くいきません。 intじゃダメということはわかるのですが、floatやdoubleにしたら答えがおかしくなります。 intで割り切れる数字だったらこれでいいみたいですが割り切れない奴を小数1桁表示ができません。 どうすべきでしょうか? #include <stdio.h> main() { int a,b,c; printf("整数a:"); scanf("%d",&a); printf("整数b:"); scanf("%d",&b); c=(a+b)/2; printf("平均値は%dです。",c); }