前回は、ポインターの理解が不十分なのが原因でした。
教えていただいたようにプログラムを変更したところ
なおりました。
よく考えると、当たり前のことで納得いたしました。
どうもありがとうございました。
しばらく、快調?にプログラムを作成していたのですが、
再び、よくわからない現象に遭遇しまして、恥ずかしながら、UPさせて
頂きました。
お知恵を貸していただけると、大変助かります。
作成したプログラムの概要及び、コードは以下の通りです。
問題点は、その下の書いてあります。
指定した行数分の乱数を発生して、それをファイルに一端書き込み
(プログラム1)
書き込んだものをソートプログラムで読み込む(プログラム2)という
ものなのですが、、、、
プログラム1
main(){
FILE *fp;
int line_no,i,ransu;
srand((unsigned int)time(NULL));
if((fp = fopen("ran_dat.txt","w")) == NULL){
printf("ファイル作成失敗");
exit(1);
}
printf("乱数を何行作りますか :");
scanf("%d",&line_no);
for(i = 0 ; i < line_no ; i++){
ransu = rand() % 2000;
fprintf(fp,"%d \n",ransu); ←%d \n を %d¥nと続けて書いたりした
が変化無し
}
printf(" %d 行の乱数を作りました",line_no);
fclose(fp);
}
プログラム2(ファイル読み込み部)
void file_read(void){
FILE *fp;
char buff[20];
line_no = 0; /* 行数カウンター(グローバル)初期化 */
if((fp = fopen(FILE_NAME,"r")) == NULL){
printf("ファイルが存在しません");
exit(1);/* ファイルが無ければプログラム終了 */
}
while(1){
if(fgets(buff,sizeof(buff)-1,fp) == NULL) break;
if( buff[0] == '\n' ) break; ← 「問題の行」 A
if(line_no == MAX_DATA){
printf("%d 行に達しましたので読み込みを中止します \n",MAX_DATA);
break;
}
data[line_no] = atoi(buff); /* 文字列を整数に変換 */
line_no = line_no + 1; /* 行番号をインクリメント */
}
fclose(fp); /* オープンしたファイルを閉じる:必修 */
}
問題点
プログラム2で、Aの位置に
if( buff[0] == '\n' ) break;
という行を入れてありますが、この行を入ると、ファイルを読み込まずに終了して
しまう場合がありました(ファイル末端で改行コードだけの行が来たら終了させる
目的のために入れたコードです。)
要するに、ファイルの先頭に改行コードが入っているという
事になるのですが、、、、プログラム1で作成したファイルを見ても
ファイルの先頭に改行コードが来た形跡は無く ? という状態です。
コンパイラをLSI-c86からbccに変更しても同じようにエラーになり、
データファイルを手で打ち込んで再度プログラムで読み込ませたりすると
再び正常にもどったりして、とにかく安定しません。
書き込み時でfprintf内部の制御文字を%d \n と空欄をあけていたのを
%d\nに変更したりして、バグが再現するかどうかみたのですが、どちらの場合も動い
て
しまいました。(この場合、前者の空欄を空けるのは、atoi等で正常に変換されるの
が
不思議)
なにか、忘れている事があるのでしょうか
よろしくお願いします。
"h.o" <gast...@poplor.ocn.ne.jp> wrote in message
news:bj1dsh$cco$1...@news-est.ocn.ad.jp...
プログラム1にしても,2でもよく分らないのですが,2について言えばやたら
breakが多くてなぜそんなに必要なのか理解し難い感じで゜す。で,疑問なのは,
「要するに、ファイルの先頭に改行コードが入っているという事になるのですが」と
いうのは,何を根拠にそう判断したのて゜しょうか。とりあえず,fgetsの仕様をよ
く読んでみると疑問も解決するように思いますが。(プログラムがどこで終了してい
るかdebagなりprintfなり挿入して確認すれば,分ると思いますが。)
--
******************************
keizi kounoike
******************************
解答ありがとうございます。
勉強中ゆえ、いたらない点おゆるしください。
上記質問の件ですが
なぜ ファイルの先頭に改行コードが入っていると判断したのか という点ですが
これは、printfを、この部分に挿入してみてわかりました。
詳しく説明させていただきますと
この後に読み込んだデータを表示させるプログラムがあるのですが、何も表示が出て
きませんので
おかしいと思い、いろいろ調べた結果、(printfをいろいろいれてみて)ファ
イルを読んでいないという事がわかりました。
このAの部分をコメントアウトすると問題なくプログラムが動いた点からも、この部
分が
バグであると判断いたしました。
しかしながら、上記に書きましたが、メモ帖でデータファイルを開いても、
ファイル先頭部に改行コードはみつかりません。
この部分が理解できない部分であります。
尚、break文が多いのは、本当は要素数を超えてデータを読み込もうとしたときに
mallocでデータ追加しようと考えているのですが、配列にした場合、どうすれ
ばいいのか
コードがうかばなかったので、とりあえず、要素数以上のデータを読み込もうとした
ら
そこで打ち切り、という(暫定的なプログラムにしてあります。
汚くて申し訳ありません。
現時点でプログラムは正常に動作しており、さっきのは何だったのか 謎です。
今疑っているのは、ストリームになんらかの形でデータが残っていたのではないかと
そちらを調べています。
確かフラッシュする関数があったはずだけど、思い出せない、、、、、
複雑な事はなにもしてないのでfgetsの仕様によるものではないと考えています。
まず、よほど大きなものでないかぎり、ちゃんと動くコ
ード全体を載せてください。
プログラム1はヘッダーファイルがインクルードされて
いません。もちろんstdio.hすらインクルードされてい
ないのではコンパイルすら通らないわけですから、それ
なしにコンパイルして動かないと騒いでいるわけではな
いことは理解できますが、それでも読む側がまったく同
じものを再現できないのではだめなのです。
プログラム2はそれに加えてメイン関数も大域変数も定
義されていません。それらがどう定義されているかでこ
の関数の動きが違ってくる可能性もあるのですから、少
なくとも最低限の動きをして、しかも自分が不思議に思
っている挙動をするプログラム全体を挙げる努力をして
ください。
また、プログラム2は
> 書き込んだものをソートプログラムで読み込む(プログラム2)という
> ものなのですが、、、、
とあるとおり、どこかでソートを行うはずですが、それ
はどうなっていますか? たとえばsystem()関数で外部の
ソートプログラムを呼び、その結果作られた一時ファイ
ルをfile_read()で読んでいるなら、プログラム1で作っ
たファイルの末尾に空行があって、その空行がソートの
結果先頭に来て、
> if( buff[0] == '\n' ) break; ← 「問題の行」 A
で終了してしまうことも考えられます。
とはいえプログラム1が空行を作るとも思えませんので、
空行が先頭にあるせいでデータを読み込まずに終了して
いるという推測は誤っているかもしれませんし、あるい
はまったく別の理由で、じつはデータはきちんと読み込
まれているのに行数line_noがゼロになっているなどの
可能性もあります。
とにかく、このようにプログラムを載せても誰もアドバ
イスできません。問題となる動きをするプログラム全体
を示して質問しなおしましょうね。
こちらでプログラム1、プログラム2の先頭に次の行を挿
入して動かしてみたところ、とりあえずちゃんと動いて
データも読み込まれているようです。プログラム2では
ソートを行ってはいませんが...。
プログラム1
--------------------------------------------------
#include <stdio.h>
--------------------------------------------------
プログラム2
--------------------------------------------------
#include <stdio.h>
#define FILE_NAME "ran_dat.txt"
#define MAX_DATA 100
int data[MAX_DATA];
int line_no;
void file_read(void);
main()
{
int i;
file_read();
for (i = 0; i < line_no; i++)
printf("%d\n", data[i]);
exit(0);
}
--------------------------------------------------
ついでですが、
> 書き込み時でfprintf内部の制御文字を%d \n と空欄をあけていたのを
> %d\nに変更したりして、バグが再現するかどうかみたのですが、どちらの場合も動いて
> しまいました。(この場合、前者の空欄を空けるのは、atoi等で正常に変換されるのが
> 不思議)
atoi()は渡されたアドレスから文字を順に読み、数字で
ない文字がきたら読み込みを終えます。乱数のあとに空
白が来ようが改行が来ようが、はたまた文字列の終わり
(NUL文字)が来ようが同じことです。
--
太田純(Junn Ohta) (株)リコー/新横浜事業所
oh...@sdg.mdd.ricoh.co.jp
"h.o" <gast...@poplor.ocn.ne.jp> wrote in message
news:bj20ph$m2a$1...@news-est.ocn.ad.jp...
> おかしいと思い、いろいろ調べた結果、(printfをいろいろいれてみて)
ファ
> イルを読んでいないという事がわかりました。
>
> このAの部分をコメントアウトすると問題なくプログラムが動いた点からも、この
部
> 分が
> バグであると判断いたしました。
プログラム1で作成したファイルなら,buff[0] == '\n' となることはまず無いと思
います。
で,実際Aで終わるとなると,ファイルの先頭が間違いなく'\n'であったということ
ではないでしょうか。これについては,アマチュアの私なんかより,プロの太田さん
がコメントしているので,そちらを参考にして下さい。
蛇足ですが,この状況が発生したファイルについてメモ帳ではなく例えば,cat
ran_dat.txt で表示させて見てはどうでしょうか。先頭が改行ならそのように表示さ
れるはず。
ところでそもそも,
(ファイル末端で改行コードだけの行が来たら終了させる目的のために入れたコード
です。)
if( buff[0] == '\n' ) break;
は,特に必要ないのでは。
ファイルのどの箇所であろうと,'\n'のみ のデータを無視したいのであれば,
if( buff[0] == '\n' ) continue;
でよいのではと思います。