欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C语言中scanf的一些问题

程序员文章站 2024-01-27 08:06:34
...

scanf与缓冲区

C语言没有输入输出关键字,其输入输出的操作是通过调用库函数实现的。C语言通过scanf函数读取键盘的输入(标准输入),当程序执行遇到scanf时,程序会阻塞,等到有输入时才继续执行。

程序执行时,如果遇到下面的代码:

int i = 0;		//给int型i初始化并赋初值0
char j = 0;		//空字符串
scanf("%d",&i);
printf("i = %d\n",i);
scanf("%c",&j)
printf("j = %c",j);

在执行时会出现要求输入字符时没有阻塞,直接输出空白的现象。如下图所示:

C语言中scanf的一些问题

这是因为在scanf在处理整数型、浮点型、字符串的时候,会自动忽略空格,’\n’(回车)等字符;但是在处理字符型时不会忽略任何字符,因此语句在执行第一个scanf时输入了2和回车键,2会被读取走,回车键仍然停留在缓冲区(缓冲区的相关解释见下面补充)中,被第二个scanf读取,因此会输出“j = (回车)”。

此处补充缓冲区的一些原理:

缓冲区是内存中的一段空间,由操作系统分配。C语言缓冲区有三种情况:

  1. 全缓冲

    在这种情况下,当填满标准I/O缓存后才进行实际I/O操作。全缓冲的典型代表是对磁盘文件的读写操作。

  2. 行缓冲

    在这种情况下,当在输入和输出中遇到换行符时,将执行真正的I/O操作。这时,我们输入的字符先存放到缓冲区中,等按下回车键换行时才进行实际的I/O操作。典型代表是标准输入缓冲区(stdin)和标准输出缓冲区(stdout)。

  3. 不带缓冲区

    也就是不进行缓冲,标准出错情况(stderr)是典型代表,这使得出错信息可以直接尽快地显示出来。

ANSI C(C89)要求缓存具有下列特征。

  1. 当且仅当标准输入和标准输出不涉及交互设备时,它们才是全缓存的。
  2. 标准出错绝不会是全缓存的。

在上面的例子中,就属于标准输入缓冲,我们在输入缓冲区放入的内容为字符(并不会把它当成整数型)“2\n”,在输出"\n"后,scanf才开始处理这串字符,"%d"匹配了整型(此处才把它当成整数型),然后放入变量i中,接着进行打印输出,这时’\n’仍然在标准输入缓冲区(stdin)内。被第二个scanf读取,产生如上图所示结果。

scanf函数的循环读取

有代码如下:

int main()
{
	int i = 0;
	int ret;
	while((ret = scanf("%d",&i)) != EOF)
	{
		printf("i = %d\n",i);
	}
	return 0;
}

scanf的返回值和EOF的解释见下面的补充。

在执行该程序时,如果输入a,即当输入的类型错误时,scanf函数无法匹配成功,程序仍然会进入循环,这时会导致不断地重复打印 i = 0。因为其比配成功时,数据将会从缓冲器读出,而其匹配不成功,ret的值恒为0,不为-1,程序陷入循环。

为了避免这种情况,可以在while语句中加入语句如下:

while(fflush(stdin),(ret = scanf("%d",&i)) != EOF)fflush(stdin)

因为fflush函数具有刷新(清空)标准输入缓冲区的作用。

此处为scanf的返回值和EOF的解释补充:

scanf的返回值是匹配成功的个数,例如代码

int a = 0;
char b = 'a';
float c = 1.0;
int ret = 0;
ret = scanf("%d %c%f",&a,&b,&c);		//此处的%c要加上空格,否则因为字符匹配时不会忽略任何字符,空格将会被									 //视为字符输入,通过自己加一个空格的方式来避免这种错误
printf("%d\n",ret);

scanf 函数的返回值反映的是按照指定的格式符正确读入的数据的个数。如果都匹配成功那么将会scanf将会返回3,如果只有两个匹配成功那么将会返回2。
C语言中scanf的一些问题
C语言中scanf的一些问题

但是如果输入数据与指定格式不符,则会产生输入错误。遇到输入错误,scanf函数会立即终止,返回已经成功读取的数据的个数。

比如代码的scanf改成:

ret = scanf("%d%c%f",&c,&b,&a);

那么程序的运行结果为:
C语言中scanf的一些问题
因为第一个输入的就不匹配,因此scanf在第一个字符处就终止,匹配成功0。

EOF:EOF意为End Of File代表了文件的结束,其值为-1,在程序执行时,用Ctrl+c来表示EOF。

计算机机试或者竞赛时的要求多个输入时注意事项:

可以使用如下代码来表示多个输入(比如两个),效果相同,否则将会报出Output Limit Exceeded(输出超出限制)的错误。

while(scanf("%d %d",&a,&b) != EOF)
while(scanf("%d %d",&a,&b) == 2)
while(~scanf("%d %d",&a,&b))

参考资料:

C语言scanf函数的返回值问题
【跟“龙哥”学C语言】