• 締切済み

続・EOF判定されない

前回「EOF判定されない」で回答、アドバイスしていただいた a-kumaさん、Haizyさん、inthefloiさん、anisolさん、leaz024さん、cherry-moonさん 本当にありがとうございました。頂いたアドバイスを試行してみましたが、なぜか、ダメでした。(T-T) 環境が悪いのかもしれませんね。 あれから、feof関数を使わずにファイルの終わりを算出して判定するなどの方法を試みましたが、EOF判定だけのために妙に複雑になってしまい、自分でも納得がいかなかったので、再度こちらで皆さんの意見をもらおうと投稿させてもらいました。 今回は質問の仕方を変えて、モジュールの仕様を挙げますので、それから「自分ならこうする」というようなお答えを頂けたらと思っています。 feof関数を使用しても、その他の方法でもなんでもアリです。(^^) 「ファイル一行入力モジュール」(仕様) 1.このモジュールは実行されると「inputfile.txt」から一行だけ(改行まで)読み込み、終了します。次に実行された時は、その次の行を読み込みます。 2.ファイルの終端に達したら、リターンコードに'4'を設定し、終了する。 以上これだけ。(^^; 「inputfile.txt」(仕様) インプットファイルは、テキストファイルで、一行30バイトの文字列を格納しています。ファイルの総バイト数は不定です。 文字コードは「Shift-JIS」「改行=CR+LF」、ファイルの最後にEOF制御文字を設定しています。 「インプットファイルの内容」  1行目 AAAAAAAAAABBBBBBBBBBCCCCCCCCC[改行文字]  2行目 DDDDDDDDDDEEEEEEEEEEFFFFFFFFF[改行文字]           ・           ・           ・ n-1行目 XXXXXXXXXXYYYYYYYYYYZZZZZZZZZ[改行文字]  n行目 [EOF] 「ここはこうしたらいいんじゃないかな?」的な事でかまいませんので、是非みなさんの意見を聞かせてください。

みんなの回答

  • terra5
  • ベストアンサー率34% (574/1662)
回答No.8

問題がでそうなところと言うと,[EOF](^Z)を追加しているところと、ファイルのオープン方法でしょうか。 まず、WindowsとかMS-DOS環境の場合は, fopenを使い,テキストモードにしておけば問題無いように思います。 f=fopen("inputfile.txt","r"); while( fgets(buff,sizeof(buff),f) ); if ( feof(f) ) printf("EOF\n"); みたいにするとこちらではEOF検出してます。 a-kumaさんのが仕様に忠実にできていて正しく動きそうですね。 わがままな私はこの仕様に不満があるので書きませんが(笑) ところでテキストモードですが、元々unixとのライブラリの整合性をとるためのエミュレーションモードみたいなものです。 これは、DOSやWindowsがunixと改行コードが違ったり,EOFコードがあったりしても 同じプログラムで動作するようにしたものですから、 unixはそういう変換は不要でそもそも区別する必要がなく、モードが存在しないのです。 改行等がからむ物はテキストモードにするのが簡単で間違いないですし、そのままunixでも動作させられます。 バイナリモードでオープンしてfgetsで読むとどうなるか等調べないとわからないような物は面倒です(^^;; また、EOFコードは確かCP/Mかなんかの名残であるもので、本来は不要なコードです。 必要だったのは,ファイルシステムにファイルサイズが存在しないためです。(クラスタ単位でしかわからない)

  • anisol
  • ベストアンサー率48% (146/301)
回答No.7

補足ありがとうございます。素人ですが、もうちょっと調べてみました。私の前の回答は的外れだったみたいです……。 feof()と[EOF]の組み合わせは使わないほうがいいかもしれません。というのは、feof()で[EOF]を認識させることはバイナリモードではできないようです。またUNIXではfopen()はバイナリモードしかないようで、機種依存的になります。[EOF]のコードを使わず、単純にファイルの終わりをfeof()で調べるのはだめですか? とりあえず、今まで調べた結果なので間違っているまたは的外れだったらごめんなさい。

noname#30727
noname#30727
回答No.6

私も前回の回答を見たらトホホでした。 29文字+CR+LFの31バイトに確実に固定されていて、ウィンドウズ系以外のOSであるならば、fgetsを使わずに、 char buff[31]; if (fread(buff, 1, 31, fp) < 31) {  if (feof(fp))  {   rtn_code[0] = '4';  }  else  {   rtn_code[0] = '8';  } } else {  buff[29] = '\n';  buff[30] = '\0'; } というような、やり方もあるかなと思います。

  • Haizy
  • ベストアンサー率40% (404/988)
回答No.5

こんにちは。 前回は、とろけていてゴメンナサイ。 さて、前回の最後の投稿で、触れたかもしれませんが、「改行=CR+LF」ということなので、これ自身が ”2バイト” 食っていると思います。 ですので、fgetsの第二引数(何文字読み込むか)を第一引数の限界も考慮しつつ、大きくする事が有効ではないかと思います。 【#3の例】 >char buf[1024] 完璧です。 >fgets(buf, sizeof(buf), in) ・・・・ sizeof(buf) が、文句なしの完璧です。さすがッス。こんな感じです。 同時に16進で、監視式によりbufの値を監視してみてください。 動きが変だと、ココでわかると思います。 でわ、失礼します

  • anisol
  • ベストアンサー率48% (146/301)
回答No.4

前回の質問、解決したのか気になって、夜も寝られませんでした(嘘)。早めに補足を行ってくださいね……。 ところで、 ・[EOF]はどのような方法で書きこんでいるのでしょうか。またそのコードは何ですか。 ・Windowsベースでのプログラムですか、またはUNIXベースですか。 ・単純に[EOF]だけ書きこんだファイルで、fgets(buff, 2, fp) およびfeof(fp)を実行したとき、EOF判定はされますか。(この点は重要かも) 以上お手数ですが補足していただけますか。ちょっと情報が少なすぎますので。

techtak
質問者

補足

毎度毎度説明不足でスイマセン(--: ・EOF制御文字は、秀丸エディタのオプションで「保存する時に、EOF制御文字を付加する。」にチェックを入れることでファイルに保存されています。 バイナリエディタで見ると'1A'となっています。 ・Windowsベースのプログラムです。 次に、 EOFだけを書き込んだファイルですが、秀丸では文字が記述されていないと保存できずに削除しようとするので、他のバイナリエディタを使用し1Aとだけ書いて保存しました。 それから説明不足がもう二つあります。(ホントすいません) 1.fgetsの第二引数にunsigned long型のlengthという箱を使ってます。 で、このlengthにrecord_lngsをstrtolでlong型に変換して代入しています。 unsigned long length; char record_lngs[5]; ←これには00020という文字列が格納されています。 char *endptr; char buf[32756]; length = strtol(record_lngs, &endptr, 10); if (fgets(buf, length, in) == NULL) {    if (feof(in)) {      return 4;    } } こんなかんじで実行しましたが、4は返ってきませんでした。 lengthに入ってるの20じゃダメじゃん!?と、お思いでしょうがなぜかこれでgetは正常に行われます。lengthに1や2を足してgetすると、何も読みこまれなくなります。これも謎ですね。 2.inputfile.txtは1レコード(一行)の大きさが32756バイトです。今回その1レコード(一行)に入っているデータは固定長の20バイトですが、他にも5000や,32756バイト入っている場合もあります。 こんな粗悪な説明でわかりますでしょうか?また何か説明が必要でしたら書き込んでください。(うう、もっと文章力つけとけばよかった)

  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.3

ん~、何がうまくいかないのか、よく分からんです。 と、いうわけで、提示された仕様に忠実にデータを抱えてしまっていますし、 エラーチェックもしてませんが、こんな感じの関数で良いんじゃないですか? #include <stdio.h> int xxx() {   char buf[1024];   static FILE* in = NULL;   if (in == NULL) {     in = fopen("inputfile.txt", "r");   }   if (fgets(buf, sizeof(buf), in) == NULL) {     if (feof(in)) {       return 4;     }   }   return 0; } /* テストコード */ int main() {   int ret;   int i;   for (i = 0 ; (ret = xxx()) == 0 ; ++i) { printf("%d\n", i); }   printf("ret = %d\n", ret);   return 0; }

  • kabasan
  • ベストアンサー率44% (264/588)
回答No.2

訂正!回数間違えました!! 従ってfgetsは4回行われますが、3回目で1文字以上を格納し、かつ、EOFを検出しています。つまりfgetsはNULLを返していません。このときにfeofを実行すれば「EOF検出」となるのですが、4回目を実行したためにfeofは「非EOF検出」となっています。 以上です(汗)

  • kabasan
  • ベストアンサー率44% (264/588)
回答No.1

前回の質問を今さら見ました。 まず、fgetsの使い方が間違ってます。第2引数は読みとる文字数+1なんです。つまり、テキストモードで開いた場合、20文字+改行文字で21キャラですから「22」以上を指定しなければなりません。これは、読みとった文字列の最後にナル文字を格納するためです。 従ってfgetsは5回行われますが、4回目で1文字以上を格納し、かつ、EOFを検出しています。つまりfgetsはNULLを返していません。このときにfeofを実行すれば「EOF検出」となるのですが、5回目を実行したためにfeofは「非EOF検出」となっています。 対策としては、充分な格納領域buffと読みとり文字数を引数にして、最後の行に改行があることを信じないで、毎回EOF判定する。 こんなとこでしょうか?

関連するQ&A

  • EOF判定されない

    if(fgets(buff, 21, fp) == NULL) {   if(!feof(fp))   {     rtn_code[0] = '8';   }   else   {     rtn_code[0] = '4';   } } -------------------------------------- /入力ファイル/ -------------------------------------- 1行目 AAAAABBBBBCCCCCDDDD[LF] 2行目 EEEEEFFFFFGGGGGHHHH[LF] 3行目 [EOF] -------------------------------------- [LF]=改行文字です。 [EOF]=ファイル終端指示子です。 上記のプログラムは、 1行20バイトある入力ファイルから一行だけgetするサブモジュールの一部です。 3回目にこれを実行した時に、EOFになってrtn_codeが'4'で返ってくる予定なのですが、どうしても非EOFになって'8'が返ってきてしまうのです。 なぜなんでしょうか? そもそも、どうなるとEOF指示子がfpに返ってくるのでしょう?

  • ファイル読み込み EOF 判定

    数字の羅列した単純なテキストファイルを読み込ませたいのですが、 以下のようにすると、途中で改行などで一行あけた場合、そこで読むのを ストップしてしまいます。 if (fgets(buf, sizeof(buf), fp) == NULL) { 改行にくじけることなく、ファイルの最後まで読み込ませるにはどうしたら いいのでしょうか。 ちなみに、以下のようにやると、   while(getc(fp) != EOF){ こんどは改行をものともせず、ファイルのお終いまで読んでくれるのですが、 2バイト文字(頭一文字が化ける)、のっけ一行目に数値(10桁)を置くと 一文字かけて9桁になってしまいます。 2行目以降はちゃんと10桁です。(一行目に改行をいれて、2行目以降に書くと大丈夫のようです。変) 簡単なようで、つまってます。どうかよろしくお願いします。

  • VBA 文字数の判定

    テキストファイルを1行ずつ読み取り、 100文字を超えている行のみ、新しいテキストファイルまたはexcel行に書き込んでいくという バッチを作成したいと思います。 以下でテキストファイルを1行ずつ読み取ることはできました。 1行ずつ読み取った行に対して、文字数以上の判定の方法を教えてください。 また100文字以上の場合は、別ファイルに書き込んでいく構文も教えていただけますか。 Sub test() Dim buf As String, n As Long Open "パス\a.txt" For Input As #1 Do Until EOF(1) Line Input #1, buf n = n + 1 Cells(n, 1) = buf Loop Close #1 End Sub

  • PHPでファイルポインタの移動

    現在。[EOF]になるまで1行読込んでは、ファイルポインタを移動させ すべての行を出力しています。 これをテキストの[EOF]よりも1行上のbbbbbbbbがある行(見た目上の最終行)のみを 出力したいのですがどうすればいですか? while(!feof($filepointer)){ $line = fgets($filepointer); print($line."<br />"); } ~log.txt~ aaaaaaaaaaaaa[改行コード] bbbbbbbbbbbbb[改行コード]←ココのみ取り出したい [EOF]

    • ベストアンサー
    • PHP
  • 途中にEOFがあるファイルの読込

    VB6でファイルを全行読み込んで任意の処理を行いたいのですが、そのファイルには 途中に文字コード 1a (つまりEOF)が入っている場合があります。 普通に Line Input で処理すると、その部分でファイル終了と判断し 読込を終えてしまいますが、その後のデータも読み込みたいのです。 どのようにすれば良いのでしょうか?

  • findstrで改行文字の検索

    sample.txtというファイルには通常のデータが入っており各行は改行されています。最後の行だけ改行ではなく[eof]が入っています。ファイルの中の改行されている行をすべて検索したいのですが MS-DOSのコマンドプロンプトで findstr /r \n sample.txt とやっても何も表示されません。\nを\r\nとしても同様です。 改行文字を検索するにはどうやるのでしょうか?

  • fgets関数のEOFの扱い方について

    fgets関数のEOFの扱い方って、 ファイルの終わり(EOF)を検出し、かつ配列に1文字も読み取れなかった場合、配列の内容を変化させずに残しNULLを返す。配列に1文字以上読み取れた場合、EOFをバッファに残し配列に'\0' を追加する。その後、EOFを読み取り終了。 であってますか?

  • EOFの書き込み Perl

    CGI初心者です。質問させてもらいます。 テキストファイルを読み書きモードでオープンします。 open(FILE, "+<test.txt"); 読み込みや書き込み作業をした後、 現在のファイルポインタの位置や、 seek FILE, 0, 0; などファイルの先頭で、 EOFを書き込めないのでしょうか? 例)print FILE 'EOFの文字'; Cでは出来たような気がしましたが・・ ファイルポインタの位置でファイルを終わらせる 簡単な方法ありましたら、お教え願います。m(__)m

    • ベストアンサー
    • CGI
  • EXCELのVBAでEOFを誤認識

    すみません、ファイルからデータを読み込んでいるのですが、変なコードが入っているらしく、EOFはきちんと認識できず、困っています。 文字コードも何かわからなず、半角空白でもないようです。読み込みファイルの2行目の"ー"と"&"の間にある見えない文字コードです。(さくらエディタでは半角空白に見えてます。) 何なのかも私にはわかりませんが解決方法をご教授願います。このコードを削除するば良いですが、大量にあり手動では削除困難です。 (出来れば以下のサンプルプログラムを修正する形で教えてもらえると助かります。) 簡単なVBAコードと読み込みファイルをお付けしますので、解決策をご教授方よろしくお願いします。 (以下のコードでも問題は発生します。) 添付ファイルが付けれないし、コードは変換されて表示されそうです。。。 その場合はどうやって調べれば良いかご教授頂ければと思います。 ----------VBAプログラム(Excel2007で作成)---------- Option Explicit Sub testLoadFile() Dim intFF As Integer ' FreeFile値 Dim lngREC As Long ' レコード件数カウンタ Dim strREC As String ' レコード領域 Dim opnFileName As String ' FreeFile値の取得(以降この値で入出力する) intFF = FreeFile ' 指定ファイルをOPEN(入力モード) opnFileName = ActiveWorkbook.Path & "\loadtest.txt" Open opnFileName For Input As #intFF lngREC = 0 ' ファイルのEOF(End of File)まで繰り返す Do Until EOF(intFF) ' レコード件数カウンタの加算 lngREC = lngREC + 1 ' 行単位にレコードを読み込む Line Input #intFF, strREC Cells(lngREC, 1).Value = strREC Loop ' 指定ファイルをCLOSE Close #intFF End Sub --------読み込みファイルテキスト(3行のファイルです。)------------ "aaa","3" "cccー&","4" "bbb","5"

  • 読込むtxtファイルについて

    CGIでtxtファイルからデータを読込んで、そのデータをHTMLでIFRAMEを使って表示させるようにしました。 一行だけを読込んで表示させるのですが、その読込む一行はtxtファイルでは改行もなく本当に一行で入力しているものをHTMLで表示させる時に改行したりできるのでしょうか?また、表示させる内容なんですが、HTMLのように文字のサイズを小さくしたり、色を変えたり、というのはできるのでしょうか? できるのであればその方法を教えて頂きたいです。 調べているのですが、なかなか見つからなくて。 よろしくお願いします。

    • ベストアンサー
    • CGI

専門家に質問してみよう