2012-10-22 114 views
2

我有一個作業「編寫一個C程序,允許用戶輸入多達20個整數(它將停止接受基於標記值或基於達到20個整數限制),程序應該按照與輸入相反的順序顯示數字。「測試getchar()== EOF不能正常工作

我決定讓我的哨兵值「EOF」(或CTRL + D/CRTL + Z)。我的代碼有一些非常奇怪的行爲:

  1. 你必須按EOF鍵兩次(這也創建一個計數陣列INT一個空白項
  2. 從第一項第一位數字被截斷

一切似乎工作正常,但,這顯然不是理想的效果。下面是我的代碼。你能解釋一下什麼是錯的?

main() { 
int i,iMax; 
double dblMean; 
int x[MAX]; 

printf("Please Enter Up to 20 Integers\n"); 

for (i=0; i<MAX; i++) 
{ 
    printf("%d.> ",i+1); 
    if (getchar() == EOF)   /* Check for CTRL+D OR CTRL+Z */ 
    break;       /* Exit loop if EOF entered :: Must be pressed twice and eats first character of first entry */ 
    scanf("%d",&x[i]); 
    iMax=i; 
} 

printf("\nYou entered %d numbers\n",iMax+1);    /* Should be i+1 but EOF had to be entered twice */ 
printf("\nIndex  Item  Reverse Item\n"); 
for (i=0; i<=iMax; i++) 
    printf("%3d%4c%8d%9c%11d\n",i,' ',x[i],' ',x[iMax-i]); 
return 0; 

}

編輯: 這是我最後的代碼,謝謝大家的幫助:

#include <stdio.h> 
#include <stdlib.h> 
#define MAX 20 
int main() 
{ 
    int i,iMax; 
    int x[MAX]; 

    printf("Please Enter Up to 20 Integers\n"); 

    for (i=0; i<MAX; i++) 
    { 
     printf("%d.> ",i+1); 
     if (scanf("%d",&x[i]) != 1)       /* Checks for CTRL+D OR CTRL+Z */ 
     break;            /* EOF returns -1 and loop will be exited */ 
     iMax=i;            /* iMax must be set for second loop to exit properly */ 
                  /* Can sizeof x be used instead for second loop? */ 
    } 

    printf("\nYou entered %d numbers\n",iMax+1);   /* Displays number of items entered... Will be <= MAX*/ 
    printf("\nIndex  Item  Reverse Item\n"); 
    for (i=0; i<=iMax; i++)         /* Why wont 'for (i=0; i<=sizeof x; i++)' work? */ 
     printf("%3d%4c%8d%9c%11d\n",i,' ',x[i],' ',x[iMax-i]); 
    return 0; 
} 

回答

1

getchar()調用讀取(並有效地丟棄)第一個數字,因爲它不是EOF。

你不測試scanf()工作;你應該。

for (i = 0; i < MAX; i++) 
{ 
    if (scanf("%d", &x[i]) != 1) 
     break; 
} 

此時,數組中有整數i;你並不需要在循環中設置iMax。您可以在循環退出時簡單地設置它。

+0

這對我來說非常合適!此外,僅供參考,我需要設置iMax,因爲我需要知道第二個循環停止條目的索引。如果我知道如何讓sizeof爲我工作,我可以離開iMax! –

+0

你可以簡單地在循環之後使用'iMax = i;'(我注意到,我忽略了提示'printf()')。有一次,我認爲你完全可以不用「iMax」,但我意識到,打印循環確實需要它,因爲它被寫入。不過,該版本的答案僅在10分鐘左右纔可見。 –

0

而且,除了檢查scanf函數,這裏是你需要知道: -

EOF不是字符。 EOF是getchar()在到達輸入結尾或遇到某種錯誤時返回的宏。^D不是「EOF字符」。當你在線上單擊^ D時,在linux下發生的事情是它關閉了流,並且getchar()調用到達輸入的末尾並返回EOF宏。如果您在某行的中間輸入^ D,則該流不會關閉,因此getchar()會返回它讀取的值,並且您的循環不會退出。

看到http://www.c-faq.com/stdio/getcharc.html有一個很好的描述。

+0

你是對的,EOF不是一個字符,也不是^ D。當您在終端鍵入^ D時,它會將所有可用字符發送到讀取過程。如果沒有可用的字符,那麼'read()'返回可用的0字節,並且'可用的零字節'通常被當作EOF來處理(如果你正在讀一個普通的文件,當你有'零字節'讀取文件中的每個字節)。它不*關閉流;它可以在流狀態上設置EOF位(你可以用'clearerr()'清除它),但它不會正式關閉流。 –