簡體   English   中英

驗證 C 中的字符輸入

[英]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 */
}

該方法正如所描述的:

  1. 不斷循環,
  2. 提示輸入,
  3. 讀取並驗證輸入,允許用戶通過使用Ctrl + d (或 Windows 上的Ctrl + z )生成手動EOF來取消輸入,並在執行時優雅地退出。
  4. 根據你的標准測試輸入,一個'a''b''c' ,如果你得到好的輸入, break; 讀取循環,最后
  5. 在無效輸入上,處理錯誤並重復該過程,直到獲得所需的輸入。

注意:除非您在獨立環境(沒有任何操作系統)中對微控制器進行編程,否則對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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM