简单的C语言scanf函数无法工作?

26

如果我尝试这样做:

int anint;
char achar;

printf("\nEnter any integer:");
scanf("%d", &anint);
printf("\nEnter any character:");
scanf("%c", &achar);
printf("\nHello\n");
printf("\nThe integer entered is %d\n", anint);
printf("\nThe char entered is %c\n", achar);

这允许输入一个整数,然后完全跳过第二个 scanf,这真的很奇怪,因为当我交换两个(首先输入char scanf)时,它可以正常工作。究竟出了什么问题?


1
你的指针大小不正确,anint 是一个 char 类型而 achar 是一个 int 类型。不要这样做。 - Variable Length Coder
@可变长度编码器:对不起,我在转述一个简单的例子时搞混了两个。那个打错字和我的问题无关,已经修正了例子。 - John
5个回答

33

使用 scanf 读取输入时,输入将在按下回车键后读取,但由回车键生成的换行符并不被 scanf 消耗,这意味着下一次从标准输入读取 char 时会有一个换行符准备好被读取。

避免这种情况的一种方法是使用 fgets 将输入读取为字符串,然后使用 sscanf 提取所需内容,如下:

char line[MAX];

printf("\nEnter any integer:");
if( fgets(line,MAX,stdin) && sscanf(line,"%d", &anint)!=1 ) 
   anint=0;

printf("\nEnter any character:");
if( fgets(line,MAX,stdin) && sscanf(line,"%c", &achar)!=1 ) 
   achar=0;
另一种消耗换行符的方法是 scanf("%c%*c",&anint);%*c 将从缓冲区读取换行符并丢弃它。
你可能想阅读这个: C FAQ: 为什么每个人都说不要使用 scanf?

1
在%d格式之后,您需要使用%*c(或替代它),是吗?尽管即使这样也不太可靠 - 如果用户在数字和换行符之间输入了空格或其他字符。我认为fgets()+sscanf()更好一些。 - Jonathan Leffler
3
@Jonathan: 你是正确的。在 %d 后面我们需要它。而且,使用 fgets + sscanf 总是更好的选择。 - codaddict
@codeaddict:抱歉接受有些拖延,但你确实让我更深入地了解了C语言的内部工作原理。我非常感激你提供的C FAQ链接,这样我就能更好地教授新手们这些知识,如果以后有机会帮助别人的话。 - John
/在使用scanf输入int后,使用fflush(stdin)函数来输入char/ #include<stdio.h> #include<conio.h> void main() { int x; char y; clrscr(); printf("请输入一个整数 "); scanf("%d",&x); fflush(stdin); printf("\n 现在请输入一个字符"); scanf("%c",&y); printf("\n X=%d,Y=%c",x,y); getch(); } - Rai Singh

20
其他答案都是正确的 - %c 不会跳过空白字符。使其跳过空白字符最简单的方法是在%c之前放置空白字符:
scanf(" %c", &achar);
任何格式字符串中的空格都会使 scanf 消耗掉所有连续的空格。

跳过空格如何帮助丢弃换行符?例如:scanf("\n%c", &achar);也可以工作。 - cpx
2
@cpx:因为换行符是空格。格式字符串中的任何空白字符都像其他空白字符一样,所以\n和空格一样好用(只多一个字母)。 - caf

5
它不会跳过第二个scanf(); 第二个scanf() 读取了第一个scanf() 留下的换行符。 大多数格式代码会跳过空格; %c 格式不会跳过空格。

3

在使用scanf之前调用getchar()也可以清除已存储的换行符。这种方法更轻巧,但情况有限。

char input_1;
char input_2;
getchar();
scanf("%c", &input_1);
getchar();
scanf("%c", &input_2);

将刷新换行符,在连续的代码行中更有用,当您知道它只是一个排队的值而不是字符串时


getchar解决了这个问题,帮助我辅导我妹妹的编程课程。 - josevoid

0

每次printf调用后也尝试使用_flushall()。基本上,MS的C++默认缓冲流输出,而刷新会导致输出流清空。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接