c -如何知道用户没有输入任何内容?



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

#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 somethingn");

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

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

简短的回答是:通过检查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 %dn", age);
}
else
{
// The input did not represent a valid integer
// Add error handling
}

这就提出了一个问题:如何处理"错误处理"。部分?

scanf返回EOF时,真正糟糕的事情发生了。你可以阅读errno,也许可以得到更多的信息和如何恢复的想法。这相当复杂。对于简单的程序,可以通过调用exit来终止。

scanf返回的值不同于您的期望(这里:1),这是因为下一个输入字符无法匹配。例如,用户输入是非数字字符,如ab等。最简单的错误处理是使用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 %dn", age);

说……

接受用户输入并不像听起来那么容易。在编写任何代码之前,需要做一些设计工作来指定程序认为有效的输入类型。

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

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

scanfwith%d本身将接受像"42abc"作为整数值42。程序设计者必须决定这是否可以接受。

如果用户输入的是一个大于int所能容纳的整数,你期望/接受什么?像"1234567890123456789012345678901234567890">

scanf的设计者做出了他们的选择。使用scanf的方式还增加了解析选择。作为程序设计者,你需要决定什么是你的程序可以接受的。scanf可能不是正确的工具。您可能想要查看fgets,sscanf,strtol等。

最后注意:上面的代码还允许age为负。也许可以考虑在scanf

中对age%u使用unsigned int

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

没有意义,因为如果scanf由于用户输入无效而失败,那么变量age将具有不确定的值。

您应该检查scanf的返回值,而不是检查age的值,以确定转换是否成功,例如:

#include <stdio.h>
int main( void )
{
int age;
printf( "Enter your age: " );
if ( scanf( "%d", &age ) == 1 )
{
printf( "Input was valid! It was %d.n", age );
}
else
{
printf( "Input was invalid!n" );
}
}

如果您想在一个循环中重复执行此操作,直到输入有效,那么您可以使用以下代码:

#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.

这是因为当使用%d说明符时,scanf将消耗并丢弃所有空白字符。

在处理基于行的用户输入时,通常最好不要使用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 != ''; 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.

相关内容

  • 没有找到相关文章

最新更新