天天看點

C++ scanf 函數與EOF 淺析

【摘要】

常常遇到這段代碼, while(scanf("%d",&num)!=EOF){...} ,對于 EOF 以及 scanf 函數的傳回值始終沒有好好研究過,本文将對這個問題進行一下簡單的剖析。

【正文】

【scanf 函數傳回值】

1.scanf()函數有傳回值且為int型。

2.scanf()函數傳回的值為:正确按指定格式輸入變量的個數;也即能正确接收到值的變量個數。

3.當scanf函數的第一個變量格式不正确時傳回值為0,即,當scanf函數的第n個變量格式不正确時,傳回值為n-1;

4.如果在scanf的時候在終端輸入ctrl+d,或者直接輸入異常時,scanf的傳回值将是-1。

【EOF是什麼】

EOF是end of file的縮寫,表示"文字流"(stream)的結尾。這裡的"文字流",可以是檔案(file),也可以是标準輸入(stdin)。 很自然地,我就以為,每個檔案的結尾處,有一個叫做EOF的特殊字元,讀取到這個字元,作業系統就認為檔案結束了。但是,後來我發現,EOF不是特殊字元,而是一個定義在頭檔案stdio.h的常量,一般等于-1。

#define EOF (-1)

在Linux系統之中,EOF根本不是一個字元,而是當系統讀取到檔案結尾,所傳回的一個信号值(也就是-1)。至于系統怎麼知道檔案的結尾,資料上說是通過比較檔案的長度。

是以,處理檔案可以寫成下面這樣:

  int c;

  while ((c = fgetc(fp)) != EOF)

      {

    do something

  }

但是,這樣寫也有問題。fgetc()讀取檔案的最後一個字元以後,C語言的feof()函數依然傳回0,表明沒有到達檔案結尾;隻有當fgetc()向後再讀取一個字元(即越過最後一個字元),feof()才會傳回一個非零值,表示到達檔案結尾。

是以,按照上面這樣寫法,如果一個檔案含有n個字元,那麼while循環的内部操作會運作n+1次。是以,最保險的寫法是像下面這樣:

  int c = fgetc(fp);

  while (c != EOF) 

      {

    do something;

    c = fgetc(fp);

  }

  if (feof(fp)) {

    printf("\n End of file reached.");

  } else {

    printf("\n Something went wrong.");

  }

除了表示檔案結尾,EOF還可以表示标準輸入的結尾。

  int c;

  while ((c = getchar()) != EOF) 

      {

    putchar(c);

  }

但是,标準輸入與檔案不一樣,無法事先知道輸入的長度,必須手動輸入一個字元,表示到達EOF。

Linux中,在新的一行的開頭,按下Ctrl-D,就代表EOF(如果在一行的中間按下Ctrl-D,則表示輸出"标準輸入"的緩存區,是以這時必須按兩次Ctrl-D);Windows中,Ctrl-Z表示EOF。(順便提一句,Linux中按下Ctrl-Z,表示将該程序中斷,在背景挂起,用fg指令可以重新切回到前台;按下Ctrl-C表示終止該程序。)

那麼,如果真的想輸入Ctrl-D怎麼辦?這時必須先按下Ctrl-V,然後就可以輸入Ctrl-D,系統就不會認為這是EOF信号。Ctrl-V表示按"字面含義"解讀下一個輸入,要是想按"字面含義"輸入Ctrl-V,連續輸入兩次就行了。

繼續閱讀