关于C#:如何限制用户输入


How do I limit my user input

我一直在创建一个程序,要求用户输入一个char值,但是如果他们输入多个字符,它将移至下一个函数并中断程序。 我添加了第二种方法,当输入多个输入时该方法将运行。


您的问题不是限制写入cInput的字符数之一;格式说明符%1s已经做到了。您的问题是在输入缓冲区中留下未处理的字符之一。如果后续输入无法处理它们,则需要从缓冲区中删除所有字符。例如,如果您在随后的缓冲区中保留了字母字符,但随后用%d读取,则该函数将立即返回(因为还隐式地也有换行符被缓冲),但是该字符将保持缓冲,因为它不是十进制数。如果您从不清除缓冲区,此操作将无限期继续。

对于单个字符,可以检查该字符不是换行符,然后重复获取字符,直到找到换行符为止,如下所示:

1
2
3
4
scanf("%c", &cInput ) ;
while( cInout != '\
'
&& getchar() != '\
'
) { } // flush buffered line

如果要确保用户仅输入一个字符,则可以修改上述内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
scanf("%c", &cInput ) ;   // Get a single character

if( cInput != '\
'
&&     // If the input is not"empty",
    getchar() != '\
'
)   // but the first character entered was not
                          // immediately followed by a newline...
{
    // Flush to the end of the entered line
    while( getchar() != '\
'
) { }

    // Invalidate the input to force retry
    cInput = 0 ;
}

至少要缓冲一个字符-至少要换行。有效答案将包含两个字符,其中一个在cInput中,另一个在换行符中。上面的if(...)条件读取第二个字符(如果有)(使用cInput的短路评估),并检查它是否是输入的结尾(换行符)。如果不是,它将读取所有缓冲的字符,然后使cInput无效(例如,如果输入了"No-way\
"
,则cInput包含'N'

对于数字输入,您只需读取字符,直到找到换行符:

1
2
3
scanf("%d", &nValue);
while( getchar() != '\
'
) { } // flush buffered line

如果结尾的非数字字符会使整个输入无效,则需要检查以下字符是否为换行符。

1
2
3
4
5
6
7
8
int converted = scanf("%d", &nValue);
if( converted == 0 || getchar() != '\
'
)
{
    valid_input = false ;
    while( getchar() != '\
'
) { } // flush buffered line
}

请注意,还有其他可能的解决方案。这是我的首选解决方案。

当应用于您的函数(具有其他简化形式)时:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
int intAskUser(void)
{
    char cInput = 0 ;

    while( cInput != 'N' && cInput != 'Y' )
    {
        printf("Do you want to enter a value? Y or N\
"
);
        scanf("%c", &cInput ) ;
        if( cInput != '\
'
&& getchar() != '\
'
)
        {
            while( getchar() != '\
'
) { } // flush buffered line
            cInput = 0 ;
        }
        else
        {
            cInput = toupper(cInput) ;
        }
    }

    // Return answer code 0 to 1
    return (cInput == 'N') ? 0 : 1 ;
}

int getValue(int nLower, int nUpper)
{
    assert( nLower < nUpper ) ;  // precondition check

    int nValue = 0 ;
    bool valid_input = false ;

    while( !valid_input )
    {
        printf("Enter a value between %d and %d:", nLower, nUpper ) ;
        int converted = scanf("%d", &nValue);
        if( converted == 0 || getchar() != '\
'
)
        {
            valid_input = false ;
            while( getchar() != '\
'
) { } // flush buffered line
        }

        valid_input = nValue >= nLower &&
                      nValue <= nUpper ;

        if( !valid_input )
        {
            printf("Please try again." );
        }
    }

    printf("Value: %d", nValue);
    return nValue;
}

请注意,toupper()要求包含ctype.h,类型bool要求stdbool.h


如果我正确理解了您的问题,那么您希望函数在用户输入为以下任意一项时返回

  • y,后跟换行符
  • y,后跟换行符
  • n,后跟换行符
  • n,后跟换行符

在其他所有情况下,您都希望保留在函数中并获取新的用户输入(例如,nYnhhh后跟换行符将不返回)。

据我所知,没有标准的函数可以实现这一目标,因此您必须编写自己的代码。

这样做时要记住两件事:

  • 您必须至少读取2个字符才能检查"太长"的输入字符串。
  • 输入失败后,您需要先清空输入缓冲区,然后再读取新输入。不成功的输入是没有\
    作为最后一个字符的输入。
  • 最后,我建议您使用fgets()而不是scanf(),因为它更容易使用。不过请不要使用gets()-缓冲区溢出很危险。

    您的代码可能如下所示:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <ctype.h>

    int AskUser(void)
    {
        char input[3] = {'\\0'};   // Make room for a string of 2 chars + terminating null
        int c;
        int len;

        printf("Do you want to enter a value? Y or N\
    "
    );
        do
        {
            if (!fgets(input, 3, stdin))
            {
                printf("Input error");
                exit(1);
            }

            len = strlen(input);
            if (len)
            {
                if (input[len-1] != '\
    '
    )  // Check whether last char is a newline
                {
                    // It isn't so empty the input buffer
                    while ((c = getchar()) != '\
    '
    && c != EOF) { }
                }
            }

            if (len == 2)  // Check for exactly 2 chars in input
            {
                if(toupper(input[0]) == 'Y' && input[1] == '\
    '
    )
                {
                    return 1;
                }

                if(toupper(input[0]) == 'N' && input[1] == '\
    '
    )
                {
                    return 0;
                }
            }

            printf("Please enter a valid input, Y or N: \
    "
    );        

        } while(1);
    }

    int main(void) {
        printf("Answer is %d\
    "
    , AskUser());
        return 0;
    }