如何知道用户是否没有输入任何内容?

问题描述 投票:0回答:2

我有一个问题,因为当我这样做时我的代码不工作:

#include <stdio.h>

int main() {
  int age;

  printf("Enter your age: ");
  scanf("%d", &age);

  while(age == (what do i put here)) {
    printf("\nYou have missed something\n");
            
    printf("Enter your age: ");
    scanf("%d", &age);
  }
}
c scanf
2个回答
0
投票

做类似的事情

while(age == (put something here)) {

没有意义,因为如果

scanf
由于用户输入无效输入而失败,那么变量
age
将具有不确定的值。

不是检查

age
的值,而是检查
scanf
的返回值来判断转换是否成功,例如这样:

#include <stdio.h>

int main( void )
{
    int age;

    //repeat until input is valid
    for (;;) //infinite loop, equivalent to while(1)
    {
        printf( "Enter your age: " );

        if ( scanf( "%d", &age ) != 1 )
        {
            int c;

            printf( "Invalid input! Try again.\n" );

            //discard remainder of line
            do
            {
                c = getchar();

            } while ( c != EOF && c != '\n' );

            continue;
        }

        //input was ok, so break out of the infinite loop
        break;
    }

    printf( "The input was successfully converted to %d.\n", age );
}

这个程序有以下行为:

Enter your age: abc
Invalid input! Try again.
Enter your age: 25
The input was successfully converted to 25.

但是,这个解决方案并不完美,因为它接受输入

25abc
作为数字
25
的有效输入:

Enter your age: 25abc
The input was successfully converted to 25.

在这种情况下,最好拒绝输入并提示用户输入新的输入。

另一个问题是

scanf
不会打印错误消息,如果用户输入空行也不会重新提示用户,而是会继续读取输入,直到输入非空白字符为止:

Enter your age: 


abc
Invalid input! Try again.
Enter your age: 


25
The input was successfully converted to 25.

这是因为当使用

scanf
说明符时,
%d
将消耗并丢弃所有空白字符。

在处理基于行的用户输入时,通常最好不要使用

scanf
。相反,我建议始终使用函数
fgets
将一整行输入作为字符串读取,然后尝试使用函数
strtol
.

将该字符串转换为整数

这里是一个示例程序,它修复了上述所有问题,并添加了一些额外的输入验证:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <errno.h>

//forward declaration
int get_int_from_user( const char *prompt );

int main( void )
{
    int age;

    age = get_int_from_user( "Enter your age: " );

    printf( "The input was successfully converted to %d.\n", age );
}

//This function will attempt to read one integer from the user. If
//the input is invalid, it will automatically reprompt the user,
//until the input is valid.
int get_int_from_user( const char *prompt )
{
    //loop forever until user enters a valid number
    for (;;)
    {
        char buffer[1024], *p;
        long l;

        //prompt user for input
        fputs( prompt, stdout );

        //get one line of input from input stream
        if ( fgets( buffer, sizeof buffer, stdin ) == NULL )
        {
            fprintf( stderr, "Unrecoverable input error!\n" );
            exit( EXIT_FAILURE );
        }

        //make sure that entire line was read in (i.e. that
        //the buffer was not too small)
        if ( strchr( buffer, '\n' ) == NULL && !feof( stdin ) )
        {
            int c;

            printf( "Line input was too long!\n" );

            //discard remainder of line
            do
            {
                c = getchar();

                if ( c == EOF )
                {
                    fprintf( stderr, "Unrecoverable error reading from input!\n" );
                    exit( EXIT_FAILURE );
                }

            } while ( c != '\n' );

            continue;
        }

        //attempt to convert string to number
        errno = 0;
        l = strtol( buffer, &p, 10 );
        if ( p == buffer )
        {
            printf( "Error converting string to number!\n" );
            continue;
        }

        //make sure that number is representable as an "int"
        if ( errno == ERANGE || l < INT_MIN || l > INT_MAX )
        {
            printf( "Number out of range error!\n" );
            continue;
        }

        //make sure that remainder of line contains only whitespace,
        //so that input such as "6abc" gets rejected
        for ( ; *p != '\0'; p++ )
        {
            if ( !isspace( (unsigned char)*p ) )
            {
                printf( "Unexpected input encountered!\n" );

                //cannot use `continue` here, because that would go to
                //the next iteration of the innermost loop, but we
                //want to go to the next iteration of the outer loop
                goto continue_outer_loop;
            }
        }

        return l;

    continue_outer_loop:
        continue;
    }
}

这个程序有以下行为:

Enter your age: 
Error converting string to number!
Enter your age: test
Error converting string to number!
Enter your age: 25abc
Unexpected input encountered!
Enter your age: 25
The input was successfully converted to 25.

0
投票

如何知道用户是否没有输入任何内容?

简短的回答是:通过检查

scanf
返回值

成功

scanf
返回匹配的项目数。出错时(在第一次成功匹配之前)
scanf
返回 EOF.

在代码中这将是:

int items_scanned = scanf("%d", &age);
if (items_scanned == EOF)
{
    // Input error. Could not read any input
    // Add error handling
}
else if (items_scanned == 1)
{
    // All good. Scanned one item, i.e. age now contains an integer
    printf("Age is %d\n", age);
}
else
{
    // The input did not represent a valid integer
    // Add error handling
}

这就提出了一个问题:“错误处理”部分怎么办?

scanf
返回 EOF 时,发生了一些非常糟糕的事情。人们可以阅读
errno
,并可能获得更多信息和如何恢复的想法。这相当复杂。对于简单的程序,可以通过调用
exit
.

来终止

scanf
返回的值与您期望的不同(这里:
1
)是因为无法匹配下一个输入字符。例如,用户输入的是非数字字符,如
a
b
等。最简单的错误处理是使用
getchar
读取该字符,然后再次尝试
scanf
。另一种方法是继续读取和丢弃字符,直到找到换行符。这是一个设计决定......

还有:如何继续阅读直到

age
是一个有效的整数?

使用某种循环。它可以通过许多不同的方式来完成。下面是一个非常简单的方法。

while(1)
{
    int items_scanned = scanf("%d", &age);
    if (items_scanned == EOF)
    {
        // Input error. Could not read any input
        // Add error handling
        exit(1);
    }
    else if (items_scanned == 1)
    {
        // All good. Scanned one item, i.e. age now contains an integer
        // Stop the loop
        break;
    }
    else
    {
        // The input did not represent a valid integer
        // Add error handling
        // Remove the next input character
        int tmp = getchar();
        if (tmp == EOF)
        {
            // Input error. Could not read any input
            // Add error handling
            exit(1);
        }
    }
}
// When arriving here, age is a valid integer from the user
printf("Age is %d\n", age);

就是说...

获取用户输入并不像听起来那么容易。在编写任何代码之前,需要进行一些设计工作来指定程序应认为哪种输入有效。

上面的小程序将例如接受“abc12”作为整数值 12。程序设计者必须决定是否可以接受。

同样,输入“3.14”作为整数值3。程序设计者必须决定是否可以接受。

scanf
%d
本身将接受像“42abc”这样的输入作为整数值 42。程序设计者必须决定是否可以接受。

scanf
的设计师做出了他们的选择。
scanf
的使用方式也增加了一个解析选择。作为程序设计者,您需要决定什么是您的程序可接受的。结果可能是
scanf
不是正确的工具。

© www.soinside.com 2019 - 2024. All rights reserved.