

前回「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]
「ここはこうしたらいいんじゃないかな?」的な事でかまいませんので、是非みなさんの意見を聞かせてください。
A 回答 (8件)
- 最新から表示
- 回答順に表示
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かなんかの名残であるもので、本来は不要なコードです。
必要だったのは,ファイルシステムにファイルサイズが存在しないためです。(クラスタ単位でしかわからない)
No.7
- 回答日時:
補足ありがとうございます。
素人ですが、もうちょっと調べてみました。私の前の回答は的外れだったみたいです……。feof()と[EOF]の組み合わせは使わないほうがいいかもしれません。というのは、feof()で[EOF]を認識させることはバイナリモードではできないようです。またUNIXではfopen()はバイナリモードしかないようで、機種依存的になります。[EOF]のコードを使わず、単純にファイルの終わりをfeof()で調べるのはだめですか?
とりあえず、今まで調べた結果なので間違っているまたは的外れだったらごめんなさい。
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';
}
というような、やり方もあるかなと思います。
No.5
- 回答日時:
こんにちは。
前回は、とろけていてゴメンナサイ。
さて、前回の最後の投稿で、触れたかもしれませんが、「改行=CR+LF」ということなので、これ自身が ”2バイト” 食っていると思います。
ですので、fgetsの第二引数(何文字読み込むか)を第一引数の限界も考慮しつつ、大きくする事が有効ではないかと思います。
【#3の例】
>char buf[1024]
完璧です。
>fgets(buf, sizeof(buf), in) ・・・・
sizeof(buf) が、文句なしの完璧です。さすがッス。こんな感じです。
同時に16進で、監視式によりbufの値を監視してみてください。
動きが変だと、ココでわかると思います。
でわ、失礼します
No.4
- 回答日時:
前回の質問、解決したのか気になって、夜も寝られませんでした(嘘)。
早めに補足を行ってくださいね……。ところで、
・[EOF]はどのような方法で書きこんでいるのでしょうか。またそのコードは何ですか。
・Windowsベースでのプログラムですか、またはUNIXベースですか。
・単純に[EOF]だけ書きこんだファイルで、fgets(buff, 2, fp) およびfeof(fp)を実行したとき、EOF判定はされますか。(この点は重要かも)
以上お手数ですが補足していただけますか。ちょっと情報が少なすぎますので。
この回答への補足
毎度毎度説明不足でスイマセン(--:
・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バイト入っている場合もあります。
こんな粗悪な説明でわかりますでしょうか?また何か説明が必要でしたら書き込んでください。(うう、もっと文章力つけとけばよかった)
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;
}
No.2
- 回答日時:
訂正!回数間違えました!!
従ってfgetsは4回行われますが、3回目で1文字以上を格納し、かつ、EOFを検出しています。つまりfgetsはNULLを返していません。このときにfeofを実行すれば「EOF検出」となるのですが、4回目を実行したためにfeofは「非EOF検出」となっています。
以上です(汗)
No.1
- 回答日時:
前回の質問を今さら見ました。
まず、fgetsの使い方が間違ってます。第2引数は読みとる文字数+1なんです。つまり、テキストモードで開いた場合、20文字+改行文字で21キャラですから「22」以上を指定しなければなりません。これは、読みとった文字列の最後にナル文字を格納するためです。
従ってfgetsは5回行われますが、4回目で1文字以上を格納し、かつ、EOFを検出しています。つまりfgetsはNULLを返していません。このときにfeofを実行すれば「EOF検出」となるのですが、5回目を実行したためにfeofは「非EOF検出」となっています。
対策としては、充分な格納領域buffと読みとり文字数を引数にして、最後の行に改行があることを信じないで、毎回EOF判定する。
こんなとこでしょうか?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) Excelにて、フォルダ内のTextファイルをマクロで統合すると文字化けしてしまう時の解消コード 4 2023/01/01 07:32
- Excel(エクセル) 【VBA】指定フォルダに格納中のテキストファイルをエクセルで処理し結果のエクセルを新規フォルダに保存 1 2022/03/25 14:19
- Excel(エクセル) マクロでテキストファイルを読み込んだ際の最終セルにデータと改行が含まれる問題の改善方法 2 2022/03/25 16:50
- UNIX・Linux テキストファイルをページ番号付きでコマンドラインから印刷したい 1 2023/02/22 12:47
- システム CSVファイルのマッピング処理の省力化 1 2022/11/24 00:01
- Visual Basic(VBA) エクセルのマクロについて教えてください。 1 2023/08/08 11:02
- Visual Basic(VBA) excelにて、特定の列に数字入力してあれば、入力してある行コピーして 別ファイルに張り付ける 2 2022/08/11 05:33
- Visual Basic(VBA) 指定月分の顧客データファイルを統合して並べ替え、所定の場所に貼り付ける (再質問) 4 2022/09/14 22:51
- Visual Basic(VBA) 3つのプロシージャをまとめたら実行時エラー発生で対応不能 6 2022/05/17 01:47
- Visual Basic(VBA) エクセルのマクロについて教えてください。 2 2023/07/15 15:48
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
テキストファイルの行数を取得...
-
ファイル内のデータを1行削除...
-
winsock recvでの文字化け
-
バイナリファイルをテキストフ...
-
テキストファイルの先頭への文...
-
テキストファイルの文字列の削除
-
ファイルポインタが動かない・・・
-
InternetReadFileで大きいファ...
-
(UWSC)このような場合、解決策...
-
fgetsで2行目から文字化け
-
ファイル読み込みについて
-
0x00をファイル出力
-
【C言語】テキスト読み込みの行...
-
改行までの一文字ずつのファイ...
-
ファイルからの読み込み
-
fgetsで、、、
-
DOSでメモ帳を開いても改行され...
-
VS2010 MFC CStdioFileについて
-
【VB.Net】バイト型配列に読み...
-
C言語初心者の質問失礼します。
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
バイナリファイルをテキストフ...
-
テキストファイルの行数を取得...
-
ファイル内のデータを1行削除...
-
巨大なテキストファイル(可変...
-
複数テキストファイルを読み込...
-
fgetsで2行目から文字化け
-
【VB.Net】バイト型配列に読み...
-
改行までの一文字ずつのファイ...
-
C言語での改行コードの扱いにつ...
-
InternetReadFileで大きいファ...
-
C/C++ ファイル入出力操作 (長...
-
fopenで開いたファイルのサイズ...
-
fopen(書き込みモード)でファイ...
-
テキストファイルの文字列の削除
-
ファイル読み込みについて
-
C言語のローカル変数の使い方に...
-
freadとfwrite
-
EOF判定されない
-
続・EOF判定されない
-
fortranで文字列を読み込む際の...
おすすめ情報