scanf函数,getchar函数和缓冲区

目录

一、scanf函数

1.函数原型

2.返回值

3.常见的格式说明符

二、getchar()函数

函数原型

三、缓冲区

行缓冲

scanf()的特性

 清空输入缓冲区

使用getchar()清空缓冲区

使用scanf()清空缓冲区

其他方式

fllush(stdin)


本文只是对scanf函数、getchar函数简单的说明,以及对缓冲区简单的介绍 

一、scanf函数

1.函数原型

int scanf( const char *format [,argument]... );

        scanf函数是C语言中一个标准输入函数,被声明在头文件stdio.h中。

        一般形式为:       

        scanf("格式控制字符串",地址表列);        

        将键盘上输入的数据,按照用户指定的格式,存储到相应的变量之中。

2.返回值

        函数返回值为int型。scanf函数成功读入数据则会返回读入数据的项数,返回值为 0 表示未分配任何字段。尝试读取字符时遇到文档末尾字符或字符串末尾字符,则返回值为 EOF。

例子:

#include<stdio.h>
int main()
{
	int ret = 0;
	int a = 0;
	int b = 0;
	ret = scanf("%d,%d", &a, &b);
	printf("%d", ret);
	return 0;
}

 运行结果:

 scanf函数成功读入数据时,会返回读入数据的项数。

 

 只有第一项读取成功时,则会返回1;当第一项读取失败时,则返回0。

如果遇到错误或遇到结束标志,返回值为EOF(EOF就是end of file,值为-1)。

end of file这个操作可以敲击Ctrl+z 或者Ctrl+d(vs中需要敲击Ctrl+z三次)。

知道这一点,那么就可以写一个循环来实现多组输入输出:

#include<stdio.h>
int main()
{
    int a = 0;
    int b = 0;
    while (scanf("%d", &a) != EOF)
    {
        printf("a=%d
", a);
    }
    return 0;
}

 

3.常见的格式说明符

数据类型 格式说明符
int %d
long %ld
float %f
double %lf
char %c
字符串(char类型数组) %s

二、getchar()函数

函数原型

getchar()标准C库函数,用来读取单个字符的函数。

int getchar( void );

 返回值为int型,参数为void。

getchar返回的是字符的ASCII码值,所以是int型;在getchar()读取结束或者失败时,会返回EOF。

例子:

int main()
{
	int ch = getchar();
	putchar(ch);
	return 0;
}

putchar()是标准C库函数,用来输出字符。 

这里可以看出getchar只会读取一个字符。

 while循环连续读取单个字符

#include<stdio.h>
int main()
{
	int ch = 0;
	while ((ch = getchar()) != EOF)
	{
		putchar(ch);
	}
    if(ch==EOF)
    {
        printf("%d",ch);
    }
	return 0;
}

运行结果:


三、缓冲区

       缓冲区(Buffer)又称为缓存(Cache),是内存空间的一部分。计算机在内存中预留了一定的存储空间,用来暂时存储输入或输出的数据,这部分预留的空间就叫做缓冲区(缓存)。

         我们输入一串字符串时,当我们按下回车键时,才会进行打印,如果我们不按下回车键,就可以一直输入,这种就是缓冲输入。但是当我们按下任意键,则会立即有响应,这种就是无缓冲输入。

       根据缓冲区的输入输出设备可以分为输入缓冲区和输出缓存区。

       根据数据刷新的时机可以分为:全缓冲、行缓冲和不带缓冲。这里只简单的说明行缓冲。

行缓冲

        当在输入和输出中遇到换行符时,才会执行真正的输入输出操作。行缓冲的典型代表就是键盘输入数据。

scanf()的特性

当遇到scanf函数时,程序会先检查输入缓冲区中是否存在数据:

        如果没有数据,就等待用户输入。用户从键盘输入的每个字符都会暂存在缓冲区中,直到用户按下回车键,产生换行符
,输入结束,scanf()才会从缓冲区中读取数据,并赋值给变量。

        如果有数据,那就看数据是否符合格式字符串的规则。

scanf函数会忽略一些空白字符,例如空格、换行符、制表符等。

 一些简单的例子

#include<stdio.h>
int main()
{
	int a = 0;
	int b = 0;
	int c = 0;
	scanf("%d", &a);
	scanf("%d", &b);
	scanf("%d", &c);
	printf("a=%d,b=%d,c=%d
", a, b, c);
	return 0;
}

运行结果:

可以看出scanf在进行读取时忽略了空格和
,缓冲区就只有空格和

那为什么会说scanf忽略了换行符

#include<stdio.h>
int main()
{
	int a = 0;
	int b = 0;
	int c = 0;
	scanf("%d", &a);
	b = getchar();
	printf("%d
", b);
	printf("%d
", a);
	return 0;
}

运行结果:

可以看到这里的getchar()读取了ASCII码为10的字符,也就是换行符
,也就是说明scanf函数不会读取换行符

从这两个代码中不难看出,从键盘中输入的数据会暂存在输入缓冲区中,函数再去读取这些数据,程序结束后,释放缓冲区。

 清空输入缓冲区

使用getchar()清空缓冲区

int c;
while((c = getchar()) != '
' && c != EOF);

使用scanf()清空缓冲区

scanf("%*[^
]"); 
scanf("%*c");

        %*[^
]:匹配处理
以外的所有字符,不赋值给变量。

        %*c:的意思是匹配一个字符(%c 是匹配字符),但不把它赋值给变量。 

        第一个scanf()会从缓冲区中读取
以外的字符,不赋值给变量,也就相当于丢弃,此时缓冲区中只有一个
,而第二个scanf()就是将这个
读取并丢弃。

其他方式

fllush(stdin)

根据C 标准,使用 fflush(stdin) 是未定义的行为,这种用法只在部分编译器上有作用,通用性差,不建议使用。