これが私のCソースコードです。
Ubuntuでビルドすると、文字を取得し始めますが、プログラムを終了する方法がわかりません。 ENTER またはキャリッジリターン。
EOFはどういう意味ですか?どうすればトリガーできますか?
このソースは、デニスリッチーの本にも掲載されています。
#include <stdio.h>
/* count digits, white space, others */
main ()
{
int c, i, nwhite, nother;
int ndigit[10];
nwhite = nother = 0;
for (i = 0; i < 10; ++i)
ndigit[i] = 0;
while ((c = getchar ()) != EOF)
if (c >= '0' && c <= '9')
++ndigit[c - '0'];
else if (c == ' ' || c == '\n' || c == '\t')
++nwhite;
else
++nother;
printf ("digits =");
for (i = 0; i < 10; ++i)
printf (" %d", ndigit[i]);
printf (", white space = %d, other = %d\n", nwhite, nother);
}
通常、ターミナルで実行されているプログラムでEOFをトリガーできます。 CTRL+D 最後の入力フラッシュの直後のキーストローク。
EOFはどういう意味ですか?どうすればトリガーできますか?
EOFはファイルの終わりを意味します。
この場合の「トリガーEOF」とは、おおよそ「入力が送信されないことをプログラムに認識させる」ことを意味します。
この場合、getchar()
は文字が読み込まれないと負の数を返すため、実行は終了します。
ただし、これは特定のプログラムだけでなく、さまざまなツールにも適用されます。
一般に、「EOFのトリガー」は、 CTRL+D 最後の入力フラッシュの直後のキーストローク(つまり、空の入力を送信する)。
たとえば、cat
の場合:
% cat >file # Hit ENTER
foo # Hit ENTER and CTRL+D
%
打つときにボンネットの下で何が起こっているのか CTRL+D 最後の入力フラッシュ以降に入力された入力がフラッシュされることです。これが空の入力である場合、プログラムのSTDINで呼び出されたread()
syscallは0
を返し、getchar()
は負の数を返します(GNUの-1
_ Cライブラリ)、これは順番にEOFとして解釈されます1。
TL; DR:EOFは文字ではなく、入力読み取り関数の負の戻り値を評価するために使用されるマクロです。使用できます Ctrl+D 関数が-1
を強制的に返すEOT
文字を送信する
すべてのプログラマーはRTFMでなければなりません
Harbison and Steele、第4版の「C A Reference Manual」を参照してください。 1995年、317ページから:
負の整数EOFは、「実文字」のエンコードではない値です。 。 。たとえば、fget(セクション15.6)は、ファイルの終わりでEOFを返します。これは、読み取られる「実際の文字」がないためです。
本質的にEOF
は文字ではなく、stdio.h
を実装して-1
を表す整数値です。したがって、kosの答えはそれに関する限り正しいですが、「空の」入力を受け取ることについてではありません。重要な注意点は、ここでEOFは戻り値(getchar()
の)比較として機能し、実際の文字を示すものではないということです。 man getchar
はそれをサポートします:
戻り値
fgetc()、getc()、およびgetchar()は、intまたはEOFにキャストされた符号なし文字として読み取られた文字を、ファイルまたはエラーの終わりで返します。
gets()およびfgets()は、成功するとsを返し、エラーまたは文字が読み取られていないときにファイルの終わりが発生するとNULLを返します。
ungetc()は成功するとcを返し、エラーの場合はEOFを返します。
while
ループを考えてください-その主な目的は、アクションを繰り返すことです括弧内の条件がtrueの場合。もう一度見てください:
while ((c = getchar ()) != EOF)
基本的に、c = getchar()
が成功したコードを返す場合(0
以上;これはよくあることです。成功したコマンドを実行してから、echo $?
、失敗したecho $?
を確認し、返される数値を確認します)。したがって、文字を取得してCにアッシングすることに成功した場合、返されるステータスコードは0、失敗は-1です。 EOF
は-1
として定義されます。したがって、条件-1 == -1
が発生すると、ループが停止します。そして、それはいつ起こりますか?取得する文字がなくなったとき、c = getchar()
が失敗したとき。 while ((c = getchar ()) != -1)
と書くことができ、それでも動作します
また、実際のコードに戻りましょう。stdio.h
からの抜粋です。
/* End of file character.
Some things throughout the library rely on this being -1. */
#ifndef EOF
# define EOF (-1)
#endif
ASCIIコードとEOT
EOF文字は実際の文字ではありませんが、ASCII 10進数値04を持つEOT
(伝送終了)文字が存在します。にリンクされています Ctrl+D ショートカット(メタ文字^D
としても表されます)。コンピュータが電話接続を制御するために使用されたときに、データのストリームの終了を示すために使用される伝送終了特性。
そのため、そのascii値をプログラムに送信することが可能です。EOTである$'\04'
に注意してください。
skolodya@ubuntu:$ ./a.out <<< "a,b,c $'\04'"
digits = 1 0 0 0 1 0 0 0 0 0, white space = 2, other = 9
したがって、それは存在すると言うことができますが、印刷できません
サイドノート
過去のコンピューターは汎用性がなかったことをよく忘れます-デザイナーは利用可能なすべてのキーボードキーを使用する必要があります。したがって、CtrlDを使用してEOT
文字を送信することは、大文字のA、ShiftAを入力するのとは異なり、依然として「文字を送信する」ことになります。したがって、EOTはユーザーから来たという意味で実際のキャラクターであり、コンピューターで読み取り可能です(印刷可能ではなく、人間には見えません)が、コンピューターのメモリに存在します
バイトコマンダーのコメント
/ dev/nullから読み取ろうとすると、EOFも返されるはずですよね?または私はそこに何を着ますか
はい、正確です。/dev/null
には実際に読み取る文字がないため、c = getchar()
は-1
コードを返し、プログラムはすぐに終了します。繰り返しますがコマンドはEOFを返しません。 EOFは、getchar関数の戻りコードを比較するために使用する-1に等しい定数変数です。 EOF
は文字として存在せず、stdio.h
内の単なる静的な値です。
デモ:
# cat /dev/null shows there's no readable chars
DIR:/xieerqi
skolodya@ubuntu:$ cat /dev/null | cat -A
# Bellow is simple program that will open /dev/null for reading. Note the use of literal -1
DIR:/xieerqi
skolodya@ubuntu:$ cat readNull.c
#include<stdio.h>
void main()
{
char c;
FILE *file;
file = fopen("/dev/null", "r");
if (file)
{
printf ("Before while loop\n");
while ((c = getc(file)) != -1)
putchar(c);
printf("After while loop\n");
fclose(file);
}
}
DIR:/xieerqi
skolodya@ubuntu:$ gcc readNull.c -o readNull
DIR:/xieerqi
skolodya@ubuntu:$ ./readNull
Before while loop
After while loop
coの中のもう一つの釘
EOFが次のようなコードを持つ文字であることを証明しようとする場合があります。
#include <stdio.h>
int main(void)
{
printf("%c", EOF);
return 0;
}
問題は、charデータ型が符号付きまたは符号なしの値になる可能性があることです。さらに、これらは最小のアドレス可能なデータ型であるため、メモリが限られているマイクロコントローラーで非常に役立ちます。したがって、int foo = 25;
を宣言する代わりに、メモリが少ないchar foo = 25;
または類似したマイクロコントローラーでよく見られます。さらに、 charsは署名付きまたは署名なし 。
次のようなプログラムを使用して、バイト単位のサイズを確認できます。
#include <stdio.h>
int main(void)
{
printf("Size of int: %lu\n",sizeof(int));
printf("Sieze of char: %lu\n",sizeof(char));
//printf("%s", EOF);
return 0;
}
skolodya@ubuntu:$ ./EOF
Size of int: 4
Sieze of char: 1
ポイントは何ですか?ポイントは、EOFは-1として定義されますが、charデータ型は整数値を出力できるです。
OK 。 。 .so charを文字列として出力しようとするとどうなりますか?
#include <stdio.h>
int main(void)
{
printf("%s", EOF);
return 0;
}
明らかにエラーですが、それでもなお、エラーは興味深いことを教えてくれます。
skolodya @ ubuntu:$ gcc EOF.c -o EOF
EOF.c:関数 'main'内:EOF.c:4:5:警告:フォーマット '%s'は、タイプ 'char *'の引数を想定していますが、but argument 2のタイプは 'int'[-Wformat =] printf( "%s"、EOF);
16進数値
EOFを16進値として印刷すると、FFFFFFFF
(16ビット(8バイト)値、-1
の2の補数)が得られます。
#include <stdio.h>
int main(void)
{
printf("This is EOF: %X\n", EOF);
printf("This is Z: %X\n",'Z');
return 0;
}
出力:
DIR:/xieerqi
skolodya@ubuntu:$ ./EOF
This is EOF: FFFFFFFF
This is Z: 5A
次のコードでは、別の奇妙なことが起こります。
#include <stdio.h>
int main(void)
{
char c;
if (c = getchar())
printf ("%x",c);
return 0;
}
を押すと Shift + A 、ASCIIテーブルと明らかに同じ16進値41を取得します。しかし、 Ctrl + D 、再びffffffff
があります-c
に格納されているgetchar()
の戻り値。
DIR:/xieerqi
skolodya@ubuntu:$ gcc EOF.c -o ASDF.asdf
DIR:/xieerqi
skolodya@ubuntu:$ ./ASDF.asdf
A
41
DIR:/xieerqi
skolodya@ubuntu:$ ./ASDF.asdf
ffffffff
他の言語を参照してください
他の言語は、マクロと比較するのではなく、関数の終了ステータスを評価するために動作するため、この混乱を避けていることに注意してください。 Javaのファイルはどのように読み込まれますか?
File inputFile = new File (filename);
Scanner readFile = new Scanner(inputFile);
while (readFile.hasNext())
{ //more code bellow }
Pythonはどうですか?
with open("/etc/passwd") as file:
for line in file:
print line
EOFは、end of fileを表します。次のシンボルをトリガーする方法はわかりませんが、ファイルをパイピングして次のプログラムを実行すると、最後にEOF信号が送信されます。
echo "Some sample text" | ./a.out
a.out
はコンパイルされたソースです