C 从控制台读取字符

C 从控制台读取字符,c,scanf,getchar,C,Scanf,Getchar,我编写了一个控制台应用程序,它对int执行多个scanf 然后,我执行getchar: int x,y; char c; printf("x:\n"); scanf("%d",&x); printf("y:\n"); scanf("%d",&y); c = getchar(); 因此,尽管输入为: 1 2 a 如何解决这个问题?这是因为scanf在输入流中留下您键入的换行符。试一试 do c = getchar(); while (isspace(c)); 而不是

我编写了一个控制台应用程序,它对int执行多个scanf 然后,我执行getchar:

int x,y;
char c;
printf("x:\n");
scanf("%d",&x);
printf("y:\n");
scanf("%d",&y);
c = getchar();
因此,尽管输入为:

1
2
a

如何解决这个问题?

这是因为
scanf
在输入流中留下您键入的换行符。试一试

do
    c = getchar();
while (isspace(c));
而不是

c = getchar();

首先,
scanf
应为
scanf(“%d\n”和&x)或y。这应该能奏效

调用
fflush(stdin)
scanf
之后,丢弃
scanf
留下的输入缓冲区中任何不必要的字符(如\r\n)

编辑:正如评论中提到的
fflush
解决方案可能存在可移植性问题,所以这里是我的第二个建议。根本不要使用
scanf
,而是使用
fgets
sscanf
的组合来完成这项工作。这是一种更安全、更简单的方法,因为它允许处理错误的输入情况

int x,y;
char c;
char buffer[80];

printf("x:\n");
if (NULL == fgets(buffer, 80, stdin) || 1 != sscanf(buffer, "%d", &x))
{
    printf("wrong input");
}
printf("y:\n");
if (NULL == fgets(buffer, 80, stdin) || 1 != sscanf(buffer, "%d", &y))
{
    printf("wrong input");
}
c = getchar();

清除所需字符之前的任何空间并忽略剩余字符的方法如下

do {
    c = getchar();
} while (isspace(c));
while (getchar() != '\n');

您可以使用fflush函数清除缓冲区中的任何剩余内容,作为先前comand line输入的结果:

fflush(stdin);

getchar()
返回
int
,而不是
char
@unwind-“从标准输入(stdin)返回下一个字符。”-ascii for charIt不起作用:输入1后,它不写“y:”(参见更新的示例),但等待第二个数字,并且仅在它写“y:”-1
fflush(stdin)后才起作用
未定义。甚至(定义这样一个构造的人)说(尽管是在一个隐藏的位置)它是一个扩展:“//fflush on input stream是对C标准的扩展”。@pmg:True!(就连我也经常指出这一点)。这在SO上出现了很多,但是它可以在MSDN支持下工作(您已经链接了页面),所以<代码>“对于输入流,fflush()将丢弃已从基础文件中提取但尚未被应用程序使用的任何缓冲数据……标准未指定输入流的行为。大多数其他实现的行为与Linux相同。”
…那么在代码中使用它有多糟糕呢?下面的文本略有不同:它根本没有提到应用程序。我根本不喜欢POSIX.1-2008的描述。Linux、Windows和POSIX(有所有的注意事项)还不足以让我称之为portable。@other.anon.coward:还有,当你可以很容易地实现更多的实现时,为什么你会愿意将自己限制在Linux、Windows和POSIX(有所有的注意事项)?@pmg:关于可移植性,你绝对是对的!但是,如果我在支持Linux的平台上的实现中限制这个调用,我可以很好地将它与诸如
#ifdef Linux
之类的宏一起使用(可能的话,可以使用诸如gcc之类的C扩展)。正如您所提到的,最好遵守标准。谢谢你的见解
fflush(stdin)
根据C标准调用未定义的行为,尽管它在某些系统(实现)上定义良好,但为了提高可移植性,最好避免使用它。