2012-02-07 36 views
0

以下代碼顯示奇怪的行爲。如果我按下換行符時給出輸入,則只有它輸出​​直方圖值,否則,如果我直接輸入EOF(^ Z),則顯示全部爲零。 getchar()函數有問題,只有在按下換行符時纔會使用輸入。getchar()的行爲是否適用於此程序?

#include <stdio.h> 
#define IN 1 /* inside a word */ 
#define OUT 0 /* outside a word */ 
#define MAXLEN 50 
/* count lines, words, and characters in input */ 
main() 
{ 
    int c, i, j, nc, state; 
    int wordlength[MAXLEN]; 
    state = OUT; 
    nc = 0; 
    for (i = 0; i < MAXLEN; i++) 
     wordlength[i] = 0; 
    while ((c = getchar()) != EOF) { 
     if (c == ' ' || c == '\n' || c == '\t') { 
      if (state == IN) { 
       wordlength[nc-1]++; 
      } 
      state = OUT; 

     } 
     else if (state == OUT) { 
      //putchar('\n'); 
      state = IN; 
      nc = 0; 
     } 
     if (state == IN) { 
      ++nc; 
     } 
    } 

    for (j = 0; j < MAXLEN; j++) 
      printf("\n%d - %d",j,wordlength[j]); 

    for (i = 10; i >= 0; i--) { 
     for (j = 0; j < MAXLEN; j++) 
      printf(((wordlength[j] > i)?"|":" ")); 
     printf("\n"); 

    } 

} 
+4

請按照C99(舊C標準;當前標準爲C2011)的要求學習編寫C語言,併爲main()函數提供顯式返回類型。當你處理命令行參數時,當你忽略參數列表和'int main(int argc,char ** argv)'時強烈推薦'int main(void)'。 – 2012-02-07 14:49:42

+0

對你而言,不幸的是,stdin通常是行緩衝的,你必須按下回車鍵來輸入你輸入的任何鍵盤輸入。就是這樣。但是,你可以使它無緩衝或使其不能做到這一點。 – 2012-02-07 14:50:19

+0

@Jonathan感謝您的建議。我正在閱讀一本書,並試圖編寫解決方案,這些解決方案只使用直到閱讀的信息。 – bubble 2012-02-07 14:56:22

回答

1

你的代碼工作或多或少三立對我來說,除非我表示EOF(控制-d我的機器前輸入輸入不跟任何空白(空格,製表符,換行符)的一個字;如果您使用Control-Z,則表示您在Windows上運行)。如果您沒有最終的空格指示EOF,則最後一個單詞不會添加到直方圖中。當然,您還應該檢查單詞長度是否不太大,以免在wordlength數組之外索引(if (nc > MAXSIZE) nc = MAXSIZE;將所有超長單詞計爲相同大小)。

經過主處理循環之後,您應該檢查是否nc > 0,如果是,請在wordlength中增加相應的條目。

也考慮從<ctype.h>使用isspace()

我儘可能使用enum而不是#define,以便符號在調試器中可用。你小心避免了一個常見的錯誤;你將變量c變成了int,而不是char

#include <stdio.h> 

enum { IN = 1, OUT = 0 }; /* inside, outside a word */ 
enum { MAXLEN = 50 }; 

/* count lines, words, and characters in input */ 
int main(void) 
{ 
    int c, i, j, nc, state; 
    int wordlength[MAXLEN]; 
    state = OUT; 
    nc = 0; 

    for (i = 0; i < MAXLEN; i++) 
     wordlength[i] = 0; 

    while ((c = getchar()) != EOF) 
    { 
     if (c == ' ' || c == '\n' || c == '\t') 
     { 
      if (state == IN) 
      { 
       if (nc > MAXLEN) 
        nc = MAXLEN; /* All long words grouped together */ 
       wordlength[nc-1]++; 
      } 
      state = OUT; 
     } 
     else if (state == OUT) 
     { 
      state = IN; 
      nc = 0; 
     } 
     if (state == IN) 
      ++nc; 
    } 

    if (nc > 0) 
    { 
     if (nc > MAXLEN) 
      nc = MAXLEN; /* All long words grouped together */ 
     wordlength[nc-1]++; 
    } 

    for (j = 0; j < MAXLEN; j++) 
     printf("\n%d - %d", j, wordlength[j]); 

    for (i = 10; i >= 0; i--) 
    { 
     for (j = 0; j < MAXLEN; j++) 
      putchar((wordlength[j] > i) ? '|' : ' '); 
     printf("\n"); 
    } 
    return 0; 
} 

你說你的機器有問題。我會非常謹慎地聲稱在系統中發現了一個錯誤,特別是在如此明顯的調用中,如getchar()。我不能排除這種可能性,但這將是我想到的最後一件事。我會花很多時間去研究我在做錯事情之前先弄錯了什麼,然後纔想到getchar()中存在一個錯誤。


在評論中,您要求被告知爲什麼您的程序不適用於您的環境。由於您尚未(尚未)正式確定運行程序的平臺/環境,因此這是不可能的。但是,我已經證明你原來的as-posted程序在類似Unix的環境中工作得很理性(我正在MacOS X 10.7.2上測試,但它對任何其他類似的Unix-like系統)。修訂版稍微好一些;它會計算輸入的最後一個單詞,即使它沒有跟隨空格或換行符。

如果根據推斷您正在使用Windows,那麼終端I/O模型可能會有所不同。特別是,C標準要求文本文件(可能包括終端輸入)必須在EOF之前以換行符結束;最後一個換行符之後的任何字符都可能被丟棄,但這取決於平臺。二進制文件的行爲是不同的。如果上一次換行符後面的數據與您報告的行爲一致。這可能是預期的行爲 - 如果您查看未識別系統的文檔。這是P J Plauger在其優秀(但有些過時的)「標準C庫」中確定的實現之間的區別之一。但是,如果我的假設是正確的,那麼我仍然希望清楚地說明你的代碼是正確的(足夠)。麻煩在於你的期望不符合系統記錄的行爲。請注意,報告您工作的平臺有時非常重要。當你侵犯邊緣情況時,它往往更爲重要。而且你仍然很難碰到getchar()中的一個bug。順便說一句,當我測試時,我需要鍵入Control-D兩次(這就是我期望必須做的)。第一次將我輸入的字符(abc)刷新爲3字節讀取的程序;第二個也將我輸入的字符(全部爲0)刷新爲程序的0字節讀數,然後將其解釋爲EOF getchar()。我還測試了abc(最後一個空白),然後是EOF。你的代碼沒有空白,沒有統計abc;它確實包括了abc,後面跟着一個空格。

+0

你的回答描述了這個程序的預期行爲。我一直小心不要輸入任何單詞> MAXLEN。感謝您提出像枚舉和其他條件的替代方案;但編寫這個程序的重點是學習C.如果你能說出爲什麼這個程序不起作用,而不是建議替代方法來完成這項工作,我會更加感激。 – bubble 2012-02-07 15:32:08

相關問題