2017-02-16 24 views
0

由於某些原因,scanf讀取該字符,但程序不會繼續超過用於驗證字符的while循環,即使該字符有效。有時會起作用,而其他時間則不起作用。奇怪的是我沒有做任何不同的事情。有任何想法嗎?C中的Scanf字符

do 
{ 
    printf("Enter \"p\" if you want to sort and shuffle a list of players or enter \"s\" if you want to sort a list of slots: "); // prompt 
    scanf("%c", &tmp); 
} while (tmp != 'p' && tmp != 's'); 

新代碼:

printf("Enter 'p' if you want to sort and shuffle a list of players or enter 's' if you want to sort a list of slots:"); // prompt 
tmp = getchar(); 

printf("%c ",tmp); 
if (tmp == 'p') 
{ 
    size = readPlayerFile(players); // calling readPlayerFile function 
    shufflePlayers(players, size); // call shufflePlayers function 
    sortPlayers(players, size); // call sortPlayers function 
} 
else if (tmp == 's') 
{ 
    printf("hello"); 
    size = readSlotFile(slots); // calling readSlotFile function 
    sortSlot(slots, size); // call sortSlots function 

} 
+2

你有沒有做過任何基本的調試?就像使用調試器和/或調試打印語句來找出'tmp'在工作和不工作時需要什麼值? – kaylum

+0

它在我的系統上正常工作。 – Jarvis

+1

在此之前你讀過什麼?在輸入中是否留下換行符?你應該考慮使用'if(scanf(「%c」,&tmp)!= 1){...句柄錯誤...}'%c'之前的空格不是偶然的 - 它跳過空格(空格,換行符),並等待輸入其他內容(「p」或「s」)。 –

回答

1

最簡單的辦法是一家領先的空間scanf()添加到格式字符串。例如,如果要提示用戶提供了錯誤的輸入時再輸入一個字符,你可以這樣做:

​​

沒有與這種簡單的方法有問題,但。如果用戶輸入"aaap"然後輸出結果將是:

Enter "p" if you want to sort and shuffle a list of players or enter "s" if you want to sort a list of slots: aaap 
Please enter "p" or "s": Please enter "p" or "s": Please enter "p" or "s": You chose p 
Choose "a"scending or "d"escending sort: 

或者更糟的是,如果用戶輸入正確的第一個字符,後跟其他字符,如"sfffa"

Enter "p" if you want to sort and shuffle a list of players or enter "s" if you want to sort a list of slots: sfffa 
You chose s 
Choose "a"scending or "d"escending sort: Please enter "a" or "d": Please enter "a" or "d": Please enter "a" or "d": You chose a 

因爲scanf()葉輸入流中不匹配的字符,必須在再次讀取輸入流之前處理這些字符。在使用" %c"的簡單解決方案中,初始空間導致scanf()跳過前導空格字符,但將拾取其他任何字符。在現實世界中,您不能指望用戶通過提供良好行爲的輸入來進行合作。

一個典型的便攜式解決方案是在循環中使用getchar()來清除輸入操作後的輸入流。您可能需要改變輸入迴路的邏輯有點做到這一點:

#include <stdio.h> 

... 

char tmp; 
int c; 
int scanf_ret; 

do { 
    printf("Enter \"p\" if you want to sort and shuffle a list of players " 
      "or enter \"s\" if you want to sort a list of slots: "); // prompt 
    scanf_ret = scanf("%c", &tmp); 
    while ((c = getchar()) != '\n' && c != EOF) { 
     continue;     // discard extra characters 
    } 
} while (scanf_ret != 1 || (tmp != 'p' && tmp != 's')); 

調用scanf()後,進入一個循環,讀取並丟棄剩餘的輸入流中的任何字符。請注意,cint,並且EOF在循環中進行了明確測試。如果發生錯誤,或者用戶從鍵盤發出信號EOF,或者輸入已從文件重定向,則getchar()功能可能會返回EOF。在這種情況下未能測試EOF將導致無限循環條件。

即使用戶輸入了不可預知的輸入,該解決方案也能正常工作,因爲輸入流在輸入後總是被清除。並且請注意,不需要格式字符串中的前導空格。另一種解決方案是使用fgets()將一行輸入讀入緩衝區,並使用sscanf()來解析緩衝區。

#include <stdio.h> 
#include <stdlib.h> 

... 

char buffer[1000]; 
char tmp; 
int sscanf_ret; 

do { 
    printf("Enter \"p\" if you want to sort and shuffle a list of players " 
      "or enter \"s\" if you want to sort a list of slots: "); // prompt 
    if (fgets(buffer, sizeof buffer, stdin) == NULL) { 
     fprintf(stderr, "Error in fgets()\n"); 
     exit(EXIT_FAILURE); 
    } 
    sscanf_ret = sscanf(buffer, "%c", &tmp); 
} while (sscanf_ret != 1 || (tmp != 'p' && tmp != 's')); 

fgets()函數獲取輸入的一整行,通過換行,或從輸入流中獲取(sizeof buffer) - 1字符,如果緩衝器不是足夠大以容納所有字符的輸入流中和\0終止子。通過提供一個大小緩衝區,這應該工作得很好。用戶仍然可以輸入大量的字符,並且這不會溢出緩衝區,但字符會留在輸入流中以供下一次讀取操作查找。爲避免此類問題,如果還有多餘的字符,應在使用上面的getchar()循環調用fgets()後清除輸入流。

所有這些技術都有它們的位置。顯然,最後兩個比第一個更健壯,並且由於用戶不太可能在輸入提示符(包括換行符)處輸入999個字符,它們幾乎是平等的。但是,爲了避免所有的驚喜,在獲得用戶輸入之後明確地清除輸入流是最好的。

+0

感謝您的長時間解釋我不知道!因爲我仍然有問題,所以我只有提示符和tmp = getchar();無論什麼原因,它仍然不會工作,我嘗試在閱讀它後直接打印字符,它仍然不會工作。 – james

+0

如果你還沒有這樣做,你可能需要打印一個換行符來將輸出緩衝區刷新到屏幕上:'printf(「%c \ n」,tmp);'。如果您使用新代碼將編輯部分添加到問題的末尾,我會查看一下。 –

+0

謝謝我現在嘗試用新代碼編輯問題,我試圖簡化它以嘗試找到問題。奇怪的是,它可以將數字作爲字符讀取,但不能與p或s一起使用 – james

0

首先,scanf()葉子在輸入緩衝器中的\n,和緩衝下一次它被稱爲它仍然在輸入。您需要將空間添加到您的格式說明:

scanf(" %c", &tmp) 

要跳過空格字符,它可以是換行,空格或製表符。

其次,你需要檢查返回scanf(),以確保只有一個字符被發現。然後

您的代碼可以是這樣的:

#include <stdio.h> 
#include <stdlib.h> 

int main(void) { 
    char temp; 

    do { 
     printf("Enter \"p\" if you want to sort and shuffle a list of players or enter \"s\" if you want to sort a list of slots: "); // prompt 
     if (scanf(" %c", &tmp) != 1) { 
      printf("Invalid character\n"); 
      exit(EXIT_FAILURE); 
     } 
    } while (tmp != 'p' && tmp != 's'); 

    return 0; 
}