如何限制用户输入

时间:2017-02-18 18:00:41

标签: c

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

2 个答案:

答案 0 :(得分:1)

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

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

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

如果您想确保用户只输入一个字符,那么您可以修改以上内容:

scanf("%c", &cInput ) ;   // Get a single character

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

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

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

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

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

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

int converted = scanf("%d", &nValue);
if( converted == 0 || getchar() != '\n' )
{
    valid_input = false ;
    while( getchar() != '\n' ) { } // flush buffered line 
}

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

当应用于您的功能时(通过其他简化):

int intAskUser(void)
{
    char cInput = 0 ;

    while( cInput != 'N' && cInput != 'Y' )
    {
        printf("Do you want to enter a value? Y or N\n");
        scanf("%c", &cInput ) ;
        if( cInput != '\n' && getchar() != '\n' )
        {
            while( getchar() != '\n' ) { } // 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() != '\n' )
        {
            valid_input = false ;
            while( getchar() != '\n' ) { } // 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

答案 1 :(得分:0)

如果我正确理解了您的问题,您希望在用户输入为

的任何一个时返回该函数
  • y后跟新行
  • Y后跟新行
  • n后跟新行
  • N后跟新行

在所有其他情况下,您希望保留在该功能中并获得新的用户输入(例如nYnhhh后跟换行符返回)。

据我所知,没有可以实现的标准功能,所以你必须编写自己的代码。

当这样做时,有两件事需要记住:

  1. 您必须阅读至少2个字符才能检查“太长”的输入字符串。
  2. 输入失败后,您需要在读取新输入之前清空输入缓冲区。不成功的输入是没有\n作为最后一个字符的输入。
  3. 最后,我建议您使用fgets()代替scanf(),因为它更容易使用。不要使用gets() - 它很容易受到缓冲区溢出的影响。

    您的代码可能如下所示:

    #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\n");
        do
        {
            if (!fgets(input, 3, stdin))
            {
                printf("Input error");
                exit(1);
            }
    
            len = strlen(input);
            if (len)
            {
                if (input[len-1] != '\n')  // Check whether last char is a newline
                {
                    // It isn't so empty the input buffer
                    while ((c = getchar()) != '\n' && c != EOF) { }
                }
            }
    
            if (len == 2)  // Check for exactly 2 chars in input
            {
                if(toupper(input[0]) == 'Y' && input[1] == '\n')
                {
                    return 1;
                }
    
                if(toupper(input[0]) == 'N' && input[1] == '\n')
                {
                    return 0;
                }
            }
    
            printf("Please enter a valid input, Y or N: \n");         
    
        } while(1);
    }
    
    int main(void) {
        printf("Answer is %d\n", AskUser());
        return 0;
    }