2014-10-03 61 views
2

我得到這個代碼:Scanf正在被忽略,如何預防?

#include <stdio.h> 

int main(void){ 
    char ordet; 
    int again = 1; 

    while(again == 1){ 
     printf("Write a name: \n"); 

     while (ordet!='\n'){ 
      scanf("%c",&ordet); 
      if('A'<= ordet && ordet <='W') 
      { 
       printf("%c",ordet+3); 
      } 

      else if('W'<=ordet){ 
       printf("%c", ordet-22); 
      } 
     } 
     printf("\nDo you want to write a new name? 1/0"); 
     scanf("%d", &again); 
    } 
    return 0; 
} 

它運行正常第一次,但只要你按1編寫一個新的名字你永遠不會把它寫的機會,它只是不斷問:「你想寫一個新名字?「並忽略「寫一個名字:」。我已經用fflush(stdin),!= EFO和%c的空間infront進行了測試,但沒有任何效果。我怎麼能解決這個問題,因爲我真的不知道,幾天前與C開始。

+0

嘿,我忘了提,但我也嘗試過,並沒有工作:http://i.gyazo.com/2f45bed9a20cfa48454f994c0ad02e2e.png – user2989236 2014-10-03 19:11:45

+0

檢查'scanf'的返回狀態,並採取適當的行動時不消耗任何輸入。 – Soren 2014-10-03 19:15:27

+0

不要改變問題。 – Rustam 2014-10-03 19:19:30

回答

3

有2個問題,你的代碼:

  1. ordet其第一次使用之前未初始化。這是未定義的行爲。

  2. 你不復位ordet任何地方內環以外。也就是說,一旦ordet變得等於\n,則內部循環的主體不會再次執行。

要解決這個問題,你可以在內循環之前寫上類似ordet = 0的東西。在讀取again變量後,不要忘記跳過保留在緩衝區中的新行字符。

+0

這不是完全無條件的UB。 – Deduplicator 2014-10-03 19:17:32

+0

仍然是同樣的問題:http://i.gyazo.com/cbfdeec8318fadbd3498e777d1553783.png但我不確定我是否按照您的指示完成了。 – user2989236 2014-10-03 19:24:19

+0

@ user2989236你忘了在閱讀'again'變量後跳過新行字符。 – kraskevich 2014-10-03 19:27:08

3
while (ordet!='\n'){ 

ordet這裏沒有使用初始化。 Not quite UB(如果您的實現使用無符號char或簽名char沒有陷阱表示),但足夠糟糕。

 scanf("%c",&ordet); 

上面一行是唯一線潛在設定ordet。請注意,只有在ordet不是'\n'時纔會輸入以此開頭的循環。
您可能需要在進入內部循環之前重置它,或使用do-while-loop。
其實,將兩個循環更改爲do-while-loop會很好。

scanf("%d", &again); 

上面一行讀取的stdin開始了號碼,但離開換行符

這必須與消費上重複所有空白處理。
幸運的是,這很容易完成,因爲內部循環忽略空白。
更改"%c"" %c"

此外,所有scanf -invocations可能會失敗。檢查他們!

1

你從鍵盤控制檯寫所有輸入被放置在緩衝區中,scanf函數從該緩衝區中讀取但是如果在緩衝區比你的格式說明指定這些字符將保留在緩衝區更多的字符。

例如

scanf("%d", &n); 

當輸入之後的數值100,然後按回車鍵,ENTER字符被放置在緩衝器中,以及「100 \ n」個時在緩衝做的scanf(標準輸入)100從所提取的緩衝區,但\ n仍然存在。

下次再寫scanf(「%d」,& n); \ n仍然在那裏,並且不會被%d讀取,因爲它不是%d號碼。

IMO來處理這個最好的辦法是不使用與fgets從鍵盤讀取,則內容已被讀取使用的sscanf提取信息後,你想:

char buffer[128]; 
fgets(buffer, sizeof(buffer), stdin); 
sscanf(buffer, "%d", &n); 

,你還可以在之後有額外的錯誤檢查:

if (fgets(buffer, sizeof(buffer), stdin) != NULL) 
{ 
    if (sscanf(buffer, "%d", &n) ==1) 
    { 
    ... 
    } 
} 

現在你的代碼:

如果你想通過字符從鍵盤使用龜etc讀取字符

()不是的scanf() 使用C運行時函數isalpha()/ toupper()來識別字符。 在C中,一個字符是一個int,這就是爲什麼大多數函數像fgetc返回一個int而不是char。

一般來說,我會建議使用fgets()而不是一次讀取一個字符。

+0

+1最佳方法fgets()/ sscanf()'(或'strtol()')。 'scanf()'是邪惡的。 – chux 2014-10-03 19:40:42