web-dev-qa-db-ja.com

EOFとは何ですか?それをトリガーする方法は?

これが私の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);
}
11
stackprogramer

Tl; dr

通常、ターミナルで実行されているプログラムで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


1- https://stackoverflow.com/a/1516177/4316166

21
kos

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
4

EOFは、end of fileを表します。次のシンボルをトリガーする方法はわかりませんが、ファイルをパイピングして次のプログラムを実行すると、最後にEOF信号が送信されます。

echo "Some sample text" | ./a.out

a.outはコンパイルされたソースです

2
Paulius Šukys