• 締切済み

意味のよく分らないソース

http://oshiete1.goo.ne.jp/qa2846277.html 上のURLのソースについていくつか質問です。 while(!feof(stdin)) { scanf("%c", &ch); if(!feof(stdin)) printf("%c", ch); } と、書いてありますが、「!feof(stdin)」のようにいきなりエクスクラメーションマー ク(ビックリマーク)が付いていますが、これはどの様な意味になるのでしょうか? また、whileでstdinを回しているようですが、stdinはどのタイミングにどの様に入力し ているのでしょうか? ANo.4の方がcp.exeというファイル名でこのプログラムをコンパイルしたら、「cp < infile.txt > outfile.txt」と入力すると、infile.txtの内容をoutfile.txtへコピーで きると書いてあるのですが「<■■■■■>」のように「<」と「>」のマークでくくって いるのはどういう意味になるのでしょうか?

みんなの回答

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.6

#5です。 > 記述した内容を読み取ったかどうかはどの様にして判定しているのでしょうか? それはscanf関数の内部仕様に関することで、 私にはわかりません。

glarelance
質問者

お礼

そうですか、解答有り難うございました。

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.5

#3です。 > 何を判断して入力終了 書式文字列に記述した内容を読み取ったときです。 > Enter Keyを押すと、'\n'のあとに、EOFでも付いているのでしょうか? 付いていません。 Windowsの場合であれば、Ctrl+ZでもってEOFとみなします。

glarelance
質問者

お礼

>書式文字列に記述した内容を読み取ったときです。 記述した内容を読み取ったかどうかはどの様にして判定しているのでしょうか?

  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.4

一応No.2に補足しておきますが、Cの真偽値は真(非0)と偽(0)です。つまり-1でも2でも0ではないので真になります。 たとえばif(feof(stdin))の意味はif(feof(stdin)==1)では間違っており、if(feof(stdin)!=0)が正しい解釈になります。 #実はfeof()がEOFを発見したときに返る値は実装依存なので、前者で書くとEOFを判定できずに思わぬ不具合を引き起こす可能性があります 今回の質問とは直接関係のない蛇足ですが、参考までに。

glarelance
質問者

お礼

なるほど、解答有り難うございます

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.3

> scanfって改行されるまで入力される関数 そういうことではありません。scanf()は必ずしも改行(Enterキー)を求めてはいません。 入力元がたまたま標準入力だったら、Enterキーを押すことで 「入力が終わったよ」という印となる、というだけです。 表現を変えると、入力元がたまたま標準入力だったら、 Enterキーを押さないと「入力が終わったよ」という印がわからない、 というだけです。

glarelance
質問者

お礼

解答有り難うございます。 では、scanfは、改行を判断材料にしているのではないとすれば、何を判断して入力終了としているのでしょうか? 通常のキーボードからの入力の際は、Enter Keyを押すと、'\n'のあとに、EOFでも付いているのでしょうか?

  • te20
  • ベストアンサー率35% (14/40)
回答No.2

> ということは、whileやifのように真偽判定をするもので「!x」だけのようになっていたら、「x==0」という意味になるということですか? !は論理式の否定(NOT)を表す記号です。したがって、xが0(偽)の時!xは1(真)となります。!は論理演算子なので、ifやwhileの中だけではなくて、論理式が書けるところならどこにでも書けます。!feof(stdin)と言う論理式は、feof(stdin)が0のときに真となるので、feof(stdin)==0と同じ意味になります。 > コピー元ファイル名を< >でくくって入力しないとコピーできないのですが、< >ってどういう意味を持っているのでしょうか? これは、ファイル名を<>でくくっているのではありません。<、>はリダイレクトの記号で、<ファイル名はstdinをファイルにリダイレクトし、>ファイル名はstdoutをこのファイルにリダイレクトします。 詳しくはANo.1さんの示されたURL先に説明があります。

glarelance
質問者

お礼

解答有り難うございます。 なるほど、feofは、入力の終わりが来たら真(1)を返すから、ここではfeofが入力の終わりで真を返した際に、whileを終わらせるために!feofとして入力の終わりで偽を返すようにしていたということですか。 そんで、「cp < infile.txt > outfile.txt」は、「<infile.txt」と「>outfile.txt」で一括りということだったんですね。

  • aigaion
  • ベストアンサー率47% (287/608)
回答No.1

!feof(stdin)は、feof(stdin)==0と言う意味ですね。 feofはstdinが終りにこれば stdinという標準入力の終りが来ない限りループを続けるという意味です。 標準入力がコンソールであるならCtrl+Cが押されればそこが終わりとなります。 stdinの処理されるタイミングですが、標準入力がコンソールであれば 初めてscanfが呼び出された時点で入力待機します。その後コンソールで改行が押されたら開業まで処理をします。 Hellow, world![改行] と改行されれば、そこまでループをまわして文字を読み込んでそのまま出力します。 読み込む文字がなくなったら、またscanfのところで待機します。 これをCtrl+Cなどで終わりであることを指示されるまでループさせます。 標準入力stdinがファイルである場合は、もっと単純でファイルの終端が車で ファイルの中の文字を読み込んで出力することを繰り返します。 stdin、stdoutはそのソースのページの回答に詳しいものがあります。 feofはこのあたり http://www9.plala.or.jp/sgwr-t/lib/feof.html リダイレクトはこのあたり http://itpro.nikkeibp.co.jp/article/COLUMN/20060228/231093/

glarelance
質問者

お礼

>!feof(stdin)は、feof(stdin)==0と言う意味 ということは、whileやifのように真偽判定をするもので「!x」だけのようになっていたら、「x==0」という意味になるということですか? >ファイルの終端が車でファイルの中の文字を読み込んで出力することを繰り返します。 scanfって改行されるまで入力される関数なので、入力されたファイルの一番最後の行に改行が入ってなかったら、最後の行が入力されない気がするのですが、実際にはきちんとコピーされています。これはいったいどういうことなのでしょうか? 後、コマンドラインでファイルをコピーすることに使う場合、http://oshiete1.goo.ne.jp/qa2846277.htmlのANo.4の人が示しているように、コピー元ファイル名を< >でくくって入力しないとコピーできないのですが、< >ってどういう意味を持っているのでしょうか?

関連するQ&A

  • stdin,stdoutについて

    C言語を学び始めたものです stdin・stdoutがどのように機能するか分かりません またstdoutはどこに出力しているんですか #include <stdio.h> int main(void) { char ch; while(!feof(stdin)) { scanf("%c", &ch); if(!feof(stdin)) printf("%c", ch); } return 0; } このプログラムは「コンソール」入出力関数だけを使用しテキストファイルの内容を別のテキストファイルにコピーするプログラムだそうですがどのテキストファイルの内容をどこのテキストファイルにコピーしているんですか?stdin・stdoutの機能が全く分かりません。 どなたか分かる方、回答お願いします。

  • ifstream/ofstream について

    こんにちは。 よろしくお願いいたします。 ifstream で定義したファイルを open し、一端 close した後再度 open しようとすると、エラーとなります。 何が原因かわかりますでしょうか? ちなみに、インファイル.txt は何も記載していないので、下記ソースのwhileループ内には入りません。 が、whileループが有ればエラー(メッセージ:3103)が発生し、 無ければ、エラーは発生しません。 環境:XP home & ボーランドC++Builder6.0 テストしたソース: void __fastcall TForm1::Button6Click(TObject *Sender) { ifstream InFile; ofstream OutFile; char cBuf[255]; InFile.open("インファイル.txt"); if (!InFile) ShowMessage("3101"); OutFile.open("アウトファイル.txt"); if (!OutFile) ShowMessage("3002"); while (!InFile.getline(cBuf, sizeof(cBuf)).eof()) { OutFile << cBuf << endl; } // このwhileループが無ければ、エラーは発生しません。 OutFile.close(); InFile.close(); InFile.open("インファイル.txt"); if (!InFile) ShowMessage("3103"); // ここでメッセージが出力されます。 }

  • fflush(stdin)の使い方とprintf()関数getchar()関数の違いについて

    はじめまして。 現在c++を勉強し始めて1週間の初心者です。 fflush(stdin)について質問です。下記のプログラムで小文字入力したアルファベット1文字を大文字に変換して出力しています。方法(1)ではgetchar()関数とputchar()関数を使用していますがどうしてこの場合にはfflush(stdin)が必要となり、方法(2)のprintf()関数とscanf()関数を使用した場合はfflush(stdin)が必要ないのでしょうか?どなたか私のような初心者でも分かるように詳しく説明してもらいたいです。 何故かプログラムを書いているとprintf()とscanf()がよく混乱します。原因として、printf()を先に書く場合と、scanf()を先に書く場合が有るからだと思っているのですが、まだよく理屈の理解ができません。なので出来ればこれらの関数についても基本的な概念を教えていただきたいです。それと方法(2)では何故最後にscanf(%c):が無くても良いのかも良く理解できません。 どなたか是非とも回答宜しくお願いします。 #include <stdio> main void() { 方法(1) printf("\n文字を1つ入力してください:"); fflush(stdin);    char ch=getchar(); ch=ch-32; putchar(ch);    方法(2) printf("\n文字を1つ入力してください:") //fflush(stdin);必要なし???    char ch; scanf("%c",&ch); ch=ch-32; printf("%c",ch);    //scanf(%c):??? }

  • 改行を含んだ文字列を正規表現で置換するには?

    正規表現で、改行を含んだ文字列を置換しようと思っています。 例えば下の「infile.txt」にある aaa bbb という(2行にわたる)文字列を zzz という文字列に変換させたい訳です。 試しに「test.vbs」のようなコードを書いてみましたが、これでは上手く行きませんでした。 上手く変換されるようにするには、どうしたら良いでしょうか? ----------------------------------------------------- ○「test.vbs」の内容 Set fso = CreateObject("Scripting.FileSystemObject") Set inFile = fso.OpenTextFile("C:\infile.txt") Set outFile = fso.CreateTextFile("C:\outfile.txt") Set regEx = New RegExp regEx.pattern = "aaa\nbbb" repStr = "zzz" Do Until inFile.AtEndOfStream tempLine = inFile.ReadLine repLine = regEx.Replace(tempLine, repStr) outFile.WriteLine repLine Loop inFile.Close outFile.Close ----------------------------------------------------- ○「C:\infile.txt」の内容 aaa bbb ccc

  • ファイルの変換で文字化けを回避したい

    ファイル中の文字列を一部書き換える処理をしています。regEx.replaceを使って書き換えたところ、日本語が下記のように文字化けしてしまいます。 これを回避するためにどうしたら良いでしょうか? ○変換前:test1.txt <description>東京都</description> ○変換結果:test2.txt(文字化け) <description>譚ア莠ャ驛ス</description> ○スクリプト Set fso = CreateObject("Scripting.FileSystemObject") Set inFile = fso.OpenTextFile("c:\test1.txt") Set outFile = fso.CreateTextFile("c:\test2.txt") Set regEx = New RegExp regEx.pattern = "テスト" repStr = "てすと" Do Until inFile.AtEndOfStream tempLine = inFile.ReadLine repLine = regEx.Replace(tempLine, repStr) outFile.WriteLine repLine Loop inFile.Close outFile.Close

  • テキストファイル中の文字列を書き換えるスクリプトを書きたい

    テキストファイルの文字列を書き換えるスクリプトを考えています。 今、次のところまで出来るようになりました。本当は「こんにちは」の文字列を全て「HELLO」に置換したいのです。現在は一行の中で最初の「こんにちは」は置換されますが、2番目以降が置換されません。同じ行中の2番目以降も置換するには、どうしたら良いでしょうか? <置換前ファイル:sample.txtの中身> こんにちはこんにちはこんにちはこんにちは こんにちは こんにちは <置換前ファイル:sample.txtの中身> HELLOこんにちはこんにちはこんにちは HELLO HELLO <置換スクリプト> Set fso = CreateObject("Scripting.FileSystemObject") Set regEx = New RegExp Set inFile = fso.OpenTextFile("C:\static\sample.txt") Set outFile = fso.CreateTextFile("C:\static\sample1.txt") regEx.Pattern = "こんにちは" repStr = "HELLO" Do Until inFile.AtEndOfStream tempLine = inFile.ReadLine repLine = regEx.Replace(tempLine, repStr) outFile.WriteLine repLine Loop inFile.Close outFile.Close

  • スイッチのソースの書き方について

    ライントレースのタッチセンサー1つを使ってON/OFFができるようにしたいのですが 下記のソースだとライントレースをしていて、黒いラインの上にいるときにしかON/OFFできません。 これを白い部分(ラインから外れたところ)でもスイッチがきくようにするにはどのようにすればいいでしょうか? /* ライトセンサーの判定値 */ #define kuro 10 /* Touch Sensor control */ /* タッチセンサーの状態を判断 戻り値 0:タッチセンサーが押されていない 1:タッチセンサーが押されている */ int GetTouch(unsigned char ch) { if (pAnalog->Pin6[ch][pAnalog->Actual[ch]] > 1000) { return 1; } else { return 0; } } int migi(unsigned char ch) /*右まわり*/ { MotorPower(CH_C, -20); /* 出力ポートCのパワーを-20%(逆回転)に変更 */ MotorPower(CH_B, 40); /* 出力ポートBのパワーを10%(逆回転)に変更 */ return 0; } int hidari(unsigned char ch)/*左まわり*/ { MotorPower(CH_C, 40); /* 出力ポートCのパワーを10%(逆回転)に変更 */ MotorPower(CH_B, -20); /* 出力ポートBのパワーを-20%(逆回転)に変更 */ return 1; } int mae(unsigned char ch) /*前進*/ { MotorPower(CH_C,45 ); /* 出力ポートCのパワーを10%(逆回転)に変更 */ MotorPower(CH_B,40 ); /* 出力ポートBのパワーを-20%(逆回転)に変更 */ return 1; } /* Light Sensor control */ /* ライトセンサーの値を取得 */ unsigned char GetSensor(unsigned char ch) { return((unsigned char)pUart->Raw[ch][pUart->Actual[ch]][0]); } int main(void) { int R = 0; MotorReset(CH_B|CH_C); /* モーターの状態をリセット */ MotorStart(CH_B|CH_C); /* モーター起動 */ while(1) { /* 永久ループ */ if(GetTouch(CH_2) == 1){ while(GetTouch(CH_2) == 0); MotorPower(CH_B|CH_C, 0); /*出力ポートB,Cのパワーを0にする*/ while(GetTouch(CH_2) == 1); /* はなされるまで待つ */ while(GetTouch(CH_2) == 0); /*押されるまで待つ*/ MotorPower(CH_B|CH_C, 40); /*出力ポートB,Cのパワーを50、50にする*/ while(GetTouch(CH_2) == 1); } clock_t start,end; if (GetSensor(CH_3) > kuro ){ /* 入力ポート3のライトセンサーが設定値を超えている場合…*/ start = clock(); /*時間測定スタート(ここから)*/ if( R == 1 ){ migi(CH_B|CH_C); /*右回り*/ }else{ hidari(CH_B|CH_C); /*左回り*/ }//elseのカッコ }//ifのカッコ while(GetSensor(CH_3) > kuro){/* 入力ポート3のライトセンサーが設定値を超えている場合…*/ end = clock();/*時間測定終了(ここまで)*/ if(((double)(end - start)/CLOCKS_PER_SEC)>0.2){ if( R == 1 ){ hidari(CH_B|CH_C); /*左回り*/ R = 0; while(GetSensor(CH_3) > kuro);/* 入力ポート3ライトセンサーが設定値を超えている場合は待つ*/ }else{ migi(CH_B|CH_C); /*右回り*/ R = 1; while(GetSensor(CH_3) > kuro);/* 入力ポート3ライトセンサーが設定値を超えている場合は待つ*/ }//elseのカッコ }//ifのカッコ }//whileのカッコ mae(CH_B|CH_C); /*前進する*/ }//whileのカッコ }//mainのカッコ

  • ファイル入出力で

    現在ファイル入出力の項目をしているのですが、以下の内容で実行すると エラーが出てどうしても実行できません。主にどこを直せばいいのでしょうか? /* ファイルをコピーするプログラム */ #include <stdio.h> int main(void) { FILE *fin, *fout; char infile[40], outfile[40]; char str[256]; printf("コピー元ファイル = "); scanf("%39s", infile); printf("コピー先ファイル = "); scanf("%39s", outfile); if( (fin = fopen(infile, "r") ) == NULL) { printf("Input file open error.\n"); return 1; } if( (fout = fopen(outfile, "w") ) == NULL) { printf("Output file open error.\n"); fclose(fin); return 1; } while(fgets(str, sizeof(str), fin) != NULL) { fputs(str, fout); } fclose(fin); fclose(fout); return 0; } エラーは FILE 、fin, fout,NULLの未定義です。 よろしくお願いします。

  • scanf関数 バッファに残ったエンター入力の扱い

    前日質問にて以下のプログラムで、二度目のscanf()が無視されてしまう 旨質問したところ、1度目のscanfでの入力でエンターがバッファに残って いるため、それを取り込んでしまうという回答いただきました。 改善方法として(*)のscanf関数で「%c」の前に空白を入れたところ 正常に動作し、改善されたのですが、なぜ改善されたのかご教示願えませんでしょうか? よろしくお願いします #include <stdio.h> int main(void) {   int g;   char ch;      do {     printf("何ガロンですか?: ");     scanf("%d", &g);     printf("%.2fリットルです\n", 3.7854 * g);     printf("また計算しますか?Y/N : "); (*) scanf("%c", &ch);   } while(ch == 'Y' || ch == 'y');   return 0; }

  • 何バイトめか調べる

    これは、指定したテキストに整数3があった場合、 ファイル先頭から何バイトか調べるプログラムです。 実行しても何も表示されませんでした。 どこが間違ってるか教えてください。 a.txtに、abcdefghij123  と書かれているとします。   FILE *fp;   int ch,val=3;   fp=fopen("a.txt","rb")   while( !feof (fp) ){      ch=fgetc(fp);      if(ch==val)      printf("%ld", ftell(fp) ); }           fclose(fp);      return 0; }

専門家に質問してみよう