• ベストアンサー

ちょっとした疑問なんですが・・・(C言語)

何度も質問してごめんなさい! ちょっとした疑問なんですが、下記のプログラム中の、 while(!feof(in)) { ch = fgetc(in); if(!feof(in)) fputc(~ch, out); } のコードで、「while(!feof(in))」でストリーム「in」結び付けられているファイルの終わりに達していれば繰り返し処理を終えるのは分かるのですが、 なぜ、インクリメントも無くファイルの終わりまで文字を調べ進めることができるのでしょうか? 未熟者の私ですが教えて頂けないでしょうか? 【プログラム例】 #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { FILE *in, *out; unsigned char ch; if(argc!=3) { printf("使用法: <プログラム名> <入力ファイル名> " "<出力ファイル名>\n"); exit(1); } if((in = fopen(argv[1], "rb"))==NULL) { printf("入力ファイルを開くことができません\n"); exit(1); } if((out = fopen(argv[2], "wb"))==NULL) { printf("出力ファイルを開くことができません\n"); exit(1); } while(!feof(in)) { ch = fgetc(in); if(!feof(in)) fputc(~ch, out); } fclose(in); fclose(out); return 0; }

質問者が選んだベストアンサー

  • ベストアンサー
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.5

すみません。訂正。 戻り値がEOFを返すのはfgetcです。 #どこで勘違いしたんだか。 int ch; ... while ((ch = fgetc(in)) != EOF) { 書き込み のようにするということです。 まあCらしい書き方といえばそういえるし、わかりづらいといえばそうかもしれません。

Guchiken
質問者

お礼

回答ありがとうございます!!! 以後、参考にさせていただきます!! 回答本当にありがとうございました!

その他の回答 (4)

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.4

> 最後の1文字を読み込んだ直前にch=fgetc(in)がEOFを返すのではなく、 > さらに次の1文字読み込もうとしたときにEOFを返すから、 > それまでにすべての文字をfputc(~ch, out)で出力されているので > 問題は無いんじゃないでしょうか? この認識であってます。 master000さんが勘違いされています。 JIS規格の該当部分を引用しときます。 「そのストリームのファイル終了表示子がセットされている場合、又はストリームがファイルの終わりに 達している場合、そのストリームのファイル終了表示子をセットし、fgetc関数は EOFを返す」 7.19.7.1 最後のキャラクタを読み取ったときは最後のキャラクタを返し、EOFを返すわけではないですから、 上記のファイル終了表示子をセットするのは、最後に達してなおそこから 読み取ろうとしたときです。 ただまあ、ここの記述にあるとおり、fputc自体がファイル終了の情報を返すわけですから、 feofを使わないでも同じことはできます。 ただし、fputcの戻りを受けるのは unsigned char ch; だとまずいですけどね。

Guchiken
質問者

お礼

回答ありがとうございます!! 解釈があっているかちょっと不安だったので、 sakusaker7さんの回答で安心できました!ありがとうございます! >まずいですけどね。 私が勉強している本『独習C 第3版』には、 int fputc(int 文字 , FILE *ストリーム); という形式で、fputc関数が紹介されているのですが、 『「文字」はint型と定義されていますが、単にchar型を渡しても問題ありません。これは一般的によくとられる手法です』とあるんです。 別の本『新ANSI C言語辞典』で調べたところ、fputc()の戻り値は、書かれた「文字」を返すとあるんです。

  • master000
  • ベストアンサー率33% (16/48)
回答No.3

>ANo.2 最後をch = fgetc(in);で読み込むとEOF状態になり つぎのif(!feof(in)) は、feof(in)がtrueになり、!で結果falseになります。 よってfputc(~ch, out);は実行されません。 ということですね。

Guchiken
質問者

お礼

回答ありがとうございます!! 最後の1文字を ch = fgetc(in); でchに読み込んだ後、ファイル位置指示子を進めて、 さらに1文字読み込もうとした時、ch=fgetc(in); がEOFを返し、 その直後のfeof(in)が真になり、!で偽になる。 最後の1文字を読み込んだ直前にch=fgetc(in)がEOFを返すのではなく、 さらに次の1文字読み込もうとしたときにEOFを返すから、 それまでにすべての文字をfputc(~ch, out)で出力されているので 問題は無いんじゃないでしょうか? ちなみに実行しても問題はありませんでしたけど・・・・ どうなんでしょうか?私にはちょっと分かりません。

  • master000
  • ベストアンサー率33% (16/48)
回答No.2

あれ? while(!feof(in)) { ch = fgetc(in); if(!feof(in)) fputc(~ch, out); } 上のパターンだとファイル末尾の1バイトは出力されませんが いいのかな?

Guchiken
質問者

お礼

回答ありがとうございます!! >ファイル末尾の1バイトは出力されませんが どうしてファイル末尾の1バイトが表示されないんですか?? 教えて頂ければうれしいです。

noname#77845
noname#77845
回答No.1

fgetc()で一文字読み込んだ後、一文字分進めているからです。 他の関数も調べた方が勉強になると思いますよ。 fgetc() http://www9.plala.or.jp/sgwr-t/lib/fgetc.html 全般 http://www9.plala.or.jp/sgwr-t/

Guchiken
質問者

お礼

さっそくの回答ありがとうございます!! もうちょっと調べてから質問したほうが良かったみたいです…ごめんなさい! fgetc()が値を返すときに1文字分進めているんですね!わかりました!! 回答本当にありがとうございました!!