[英]Validating a character input in C
我有一個項目,我想驗證 C 中的字符輸入。我是 C 語言的新手,在編程方面也不是很有經驗。 我試圖做一個驗證循環,但它不起作用。
#include<stdio.h>
void main(){
char input;
do {
scanf("%c", &input);
while ( (input != 'a') && (input != 'b') && (input != 'c') );
printf ("wrong input");
switch(input){
case 'a':
break;
case 'b':
break;
case 'c':
break;
} while ( input != 'c');
在 C 中獲取用戶輸入並不困難,但您必須仔細注意正在讀取的內容以及未讀取的stdin
(這會在您的下一個輸入中咬你)。 適合新 C 程序員的函數之一是scanf()
。 它充滿了許多陷阱。 這里相關的陷阱是使用"%c"
格式說明符和stdin
留下的任何額外的無關字符。
"%c"
和"%[..]"
轉換說明符(以及@chux 的"%n"
說明符)不會忽略前導空格。 這是一個問題,因為按Enter鍵會在stdin
生成一個'\\n'
字符。 這意味着,如果用戶輸入的不是'a'
、 'b'
或'c'
,則從stdin
讀取的下一個字符是'\\n'
。 除非您在使用"%c"
下一次輸入之前從stdin
清空'\\n'
,否則'\\n'
字符將被視為下一個輸入——您的代碼似乎跳過了下一個輸入。 (它沒有跳過任何內容—— '\\n'
正在等待被讀取——所以scanf()
將它作為輸入讀取)。
為避免此問題,您可以在" %c"
格式說明符之前放置一個空白字符(一個space
),這將導致scanf()
在下一個非空白字符之前依次忽略任意數量的空白字符。 由於'\\n'
是空格,它會從stdin
提取並丟棄'\\n'
以允許讀取輸入的下一個字符。
但是......然后你遇到了下一個陷阱——如果用戶滑倒並輸入"de"
作為輸入怎么辦。 這使得'e'
成為在讀取'd'
后未在stdin
中讀取的無關字符。 空格不會幫助您忽略非空白字符。
有一個更好的方法——面向行的輸入
在接受用戶輸入時,與其從stdin
一次讀取一個字符,不如使用fgets()
或 POSIX getline()
一次讀取一行。 這樣,給定一個合理大小的字符數組來保存行中的字符,就會消耗整行輸入。 沒有任何可能在stdin
中留下無關字符來咬你的下一個輸入。 如果您對用戶輸入的第一個字符感興趣,只需檢查保存該行的數組中的第一個字符,例如array[0]
或簡單地*array
。
所有用戶輸入都可以並且應該使用面向行的輸入功能。 如果您需要將行的一部分轉換為單獨的值,那么您可以使用sscanf()
或字符串處理函數,如strtok()
等。好處是您可以單獨驗證輸入的讀取,然后轉換值。
如何要求某些輸入
要求用戶輸入特定輸入的方法很簡單。 您只需循環不斷地提示、閱讀和驗證用戶輸入,直到用戶提供請求的輸入。 如果提供了有效的輸入,您只需break;
讀循環。 如果接收到無效輸入,您只需輸出錯誤並再次循環,直到獲得所需的輸入。
您的情況的一個簡短示例是:
#include <stdio.h>
#define MAXC 1024 /* if you need a constant, #define one (max chars per-line) */
int main (void) {
char line[MAXC]; /* declare buffer to hold each line of input */
while (1) { /* loop continually until the user provides valid input */
fputs ("\nenter a, b or c : ", stdout); /* prompt for input */
if (fgets (line, MAXC, stdin) == NULL) { /* read entire line */
puts ("(user canceled input)"); /* handle manual EOF */
return 0;
}
/* check 1st char in array to see if it is valid, if so, break loop */
if (line[0] == 'a' || line[0] == 'b' || line[0] == 'c')
break;
/* otherwise, invalid input provided, throw error -- repeat */
fputs (" error: invalid input, not 'a', 'b' or 'c'\n", stderr);
}
printf ("\nyou entered: '%c'\n", *line); /* output value */
}
該方法正如所描述的:
EOF
來取消輸入,並在執行時優雅地退出。'a'
, 'b'
或'c'
,如果你得到好的輸入, break;
讀取循環,最后 (注意:除非您在獨立環境(沒有任何操作系統)中對微控制器進行編程,否則對main()
的正確調用是int main (void)
和int main (int argc, char *argv[])
(其中你會看到寫有等效的char **argv
。參見: C11 標准 - §5.1.2.2.1 程序啟動(p1) 。另見: main() 在 C 和 C++ 中應該返回什么? )
示例使用/輸出
使用您編寫的任何輸入例程,完成后 - 嘗試打破它。 徹底測試一下。 想想用戶可能會做的所有愚蠢的事情,看看你的代碼是否正確處理了它。 如果失敗,請修復它並重試。 例如:
$ ./bin/fgetschar_abc
enter a, b or c : My dog has fleas!
error: invalid input, not 'a', 'b' or 'c'
enter a, b or c : Cat has none!
error: invalid input, not 'a', 'b' or 'c'
enter a, b or c : Lucky cat!
error: invalid input, not 'a', 'b' or 'c'
enter a, b or c : Okay, okay!
error: invalid input, not 'a', 'b' or 'c'
enter a, b or c : b
you entered: 'b'
(嘗試使用當前代碼輸入多個字符,看看會發生什么......)
現在您可以添加您的switch()
語句並確保作為line
第一個字符的唯一字符(例如line[0]
或*line
)是'a'
、 'b'
或'c'
。 如果您更喜歡使用單個字符變量而不是使用line
的第一個字符,那么只需將line
的第一個字符分配給您的變量,例如
char input = line[0];
實現switch()
留給你。 如果您有任何其他問題,請告訴我。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.