前回「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も見ています
-
10代と話して驚いたこと
先日10代の知り合いと話した際、フロッピーディスクの実物を見たことがない、と言われて驚きました。今後もこういうことが増えてくるのかと思うと不思議な気持ちです。
-
「平成」を感じるもの
「昭和レトロ」に続いて「平成レトロ」なる言葉が流行しています。 皆さんはどのようなモノ・コトに「平成」を感じますか?
-
とっておきの手土産を教えて
お呼ばれの時や、ちょっとした頂き物のお礼にと何かと必要なのに 自分のセレクトだとついマンネリ化してしまう手土産。 ¥5,000以内で手土産を用意するとしたらあなたは何を用意しますか??
-
2024年のうちにやっておきたいこと、ここで宣言しませんか?
2024年も残すところ50日を切りましたね。 ことしはどんな1年でしたか? 2024年のうちにやっておきたいこと、 よかったらここで宣言していってください!
-
とっておきの「まかない飯」を教えて下さい!
飲食店で働く方だけが食べられる、とっておきの「まかない飯」。 働いてらっしゃる方がSNSなどにアップしているのを見ると、表のメニューには出てこない秘密感もあって、「食べたい!!」と毎回思ってしまいます。
-
EXCELのVBAでEOFを誤認識
Visual Basic(VBA)
-
EOF判定されない
C言語・C++・C#
-
sqlserverで集計結果をUPDATEしたいです
SQL Server
-
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・【大喜利】【投稿~12/2】 国民的アニメ『サザエさん』が打ち切りになった理由を教えてください
- ・ちょっと先の未来クイズ第5問
- ・【お題】ヒーローの謝罪会見
- ・これが怖いの自分だけ?というものありますか?
- ・スマホに会話を聞かれているな!?と思ったことありますか?
- ・それもChatGPT!?と驚いた使用方法を教えてください
- ・見学に行くとしたら【天国】と【地獄】どっち?
- ・【大喜利】【投稿~11/22】このサンタクロースは偽物だと気付いた理由とは?
- ・お風呂の温度、何℃にしてますか?
- ・とっておきの「まかない飯」を教えて下さい!
- ・2024年のうちにやっておきたいこと、ここで宣言しませんか?
- ・いけず言葉しりとり
- ・土曜の昼、学校帰りの昼メシの思い出
- ・忘れられない激○○料理
- ・あなたにとってのゴールデンタイムはいつですか?
- ・とっておきの「夜食」教えて下さい
- ・これまでで一番「情けなかったとき」はいつですか?
- ・プリン+醤油=ウニみたいな組み合わせメニューを教えて!
- ・タイムマシーンがあったら、過去と未来どちらに行く?
- ・遅刻の「言い訳」選手権
- ・好きな和訳タイトルを教えてください
- ・うちのカレーにはこれが入ってる!って食材ありますか?
- ・おすすめのモーニング・朝食メニューを教えて!
- ・「覚え間違い」を教えてください!
- ・とっておきの手土産を教えて
- ・「平成」を感じるもの
- ・秘密基地、どこに作った?
- ・カンパ〜イ!←最初の1杯目、なに頼む?
- ・この人頭いいなと思ったエピソード
- ・あなたの「必」の書き順を教えてください
- ・ギリギリ行けるお一人様のライン
- ・10代と話して驚いたこと
- ・大人になっても苦手な食べ物、ありますか?
- ・14歳の自分に衝撃の事実を告げてください
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
バイナリファイルをテキストフ...
-
テキストファイルの行数を取得...
-
続・EOF判定されない
-
fgetsで2行目から文字化け
-
C言語での改行コードの扱いにつ...
-
【VB.Net】バイト型配列に読み...
-
C言語初心者の質問失礼します。
-
フルパスから最後のディレクト...
-
VB.NETで他のプロジェクトで作...
-
Access クエリ実行が急に非常に...
-
絶対パスの絶対て英語で何でし...
-
FTPでputすると空ファイルが出...
-
どんなプログラムを書いても指...
-
バッファとは何ですか
-
ファイルやディレクトリの存在...
-
txtとして破綻なく読めるexeフ...
-
ExcelVBAでカレントディレクト...
-
ファイル名の先頭にアンダース...
-
VBAにてEXCEL以外のファイル(テ...
-
VC++でUTF-8のファイルを出力し...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
ファイル内のデータを1行削除...
-
テキストファイルの行数を取得...
-
バイナリファイルをテキストフ...
-
c言語 2つのファイルを行ご...
-
fgetsで2行目から文字化け
-
改行までの一文字ずつのファイ...
-
VBSで指定行に挿入
-
winsock recvでの文字化け
-
【VB.Net】バイト型配列に読み...
-
巨大なテキストファイル(可変...
-
C言語での改行コードの扱いにつ...
-
EOF判定されない
-
【C言語】テキスト読み込みの行...
-
続・EOF判定されない
-
freadでファイルを読み込んだ際...
-
fopenで開いたファイルのサイズ...
-
C言語 バイナリファイルの読み...
-
0x00をファイル出力
-
0バイトファイルの作成
-
ファイル読み込みについて
おすすめ情報