c语言输入输出及缓冲

printf和scanf的作用是程序和外设进行交互的接口,
printf可以将程序输出到屏幕上或打印机上;
scanf可以将键盘的字符输入到程序中;
但是printf和scanf并不是让程序和外设直接交互的,因为直接交互的话,一是外设读写速度慢,而是频繁读写外设易造成损伤,
因此在程序和外设之间,c语言在内存中增加了输入缓冲区和输出缓冲区,用于提高程序和外设读写的响应速度,详情见下文。

printf

printf的作用是在程序中输出指定内容到设备上:

printf("hello world!\n");

格式控制符

命令功能
%d十进制有符号整数
%u十进制无符号整数
%f浮点数
%s字符串
%c单个字符
%p指针的值
%e指数形式的浮点数
%x, %X无符号以十六进制表示的整数
%o无符号以八进制表示的整数
%g把输出的值按照%e或者%f类型中输出长度较小的方式输出
%p输出地址符
%lu32位无符号整数
%llu64位无符号整数

转义字符

命令功能
\n换行
\f清屏并换页
\r回车
\tTab符
\xhh表示一个ASCII码用16进表示

scanf

# include <stdio.h>
int scanf(const char *format, ...);
scanf("%d%d", &i, &j);

scanf的作用是输入指定内容到变量中;
格式化控制符的作用是将键盘的内容格式化后保存到变量中;
需要注意的是,scanf的变量参数是指针格式,普通变量一定要取址。
输入数据时,遇到三种情况则默认输入结束。第一,遇到空格,回车,tab键。第二,规定的宽度结束时。第三,非法输入。

格式化控制符

命令功能
%c把输入解释成一个字符,如果前边加一个空格,即" %c",那么的scanf会忽略输入设备前边的空白项,直到遇到第一个字符,并只读区一个字符。
%d把输入解释成一个有符号十进制整数
%e,%f,%g,%a把输入解释成一个浮点数(%a是C99的标准)
%E,%F,%G,%A把输入解释成一个浮点数(%A是C99的标准)
%i把输入解释成一个有符号十进制整数
%o把输入解释成一个有符号的八进制整数
%p把输入解释成一个指针(一个地址)
%s把输入解释成一个字符串:输入的内容以第一个非空白字符作为开始,并且包含直到下一个空白字符的全部字符
%u把输入解释成一个无符号十进制整数
%x,%X把输入解释称一个有符号十六进制整数

缓冲区

缓冲区是c语言为加速程序和外设的读写速度,而维护的一块内存区域,
程序运行时,CPU从内存中读取程序数据,当程序需要对外设进行读写时,内存就需要和外设进行读写,而外设的读写速度很慢,因此c语言在内存中开辟了缓冲区,使大部分和外设交互的操作都在内存中进行。

printf并不会逐个字符显示在屏幕上,而是先存在缓冲区,在特定的时机,将缓冲区一起显示在屏幕上:

1.遇到\n
2.程序结束          #include <unistd.h> sleep(3);
3.遇到输入语句
4.当缓冲区满4k时
5.fflush(stdout) 手动刷新

缓存区机制可以提高数据的读写速度,并且可以让低速的输入输出设备与高速的CPU之间协调工作。

scanf并不会从键盘逐个字符读入程序,而是先存在缓冲区,在特定的时机,将缓冲区一起输入到程序:

1.当需要读取的是整型或者浮点型时,而缓冲区中的数据是字符或符号时,因此读取会失败,数据会残留在输入缓冲区中,就会影响接下来的所有数据的读取;
解决方法:借助scanf返回值判断是否接受成功,如果接受过程有失败情况,可以先清理输入缓冲区,在重新循环接收数据,直到完全接收成功为止;

2.fgets可以指定读取size-1个字符,如果有多余的会残留在输入缓冲区中,影响下一次输入;
解决方法:scanf(“%*[^\n]”); 表示从缓冲区中接受任意字符并丢弃,只要不是\n就一直进行,遇到\n才停下

3.当先输入整型或者浮点型数据,再紧接着输入字符、字符时,前一次残留的’\n’或空格,会影响字符和字符串的输入;
解决方法:%c前面加空格 ,scanf(" %c",&ch);

printf、scanf和缓冲区

使用回车键,回车符号\n也会记录在缓冲区。

例如:

#include<stdio.h>

int main()
{
	char a='d';
	char b='d';
	printf("hello\n");

	scanf("%c",&a); //第一次输入,获取到输入e
	scanf("%c",&b); //第二次输入,获取的是缓冲区留下的\n,就是手动按下回车产生的\n

	if(a=='\n'){printf("yyy");}
	else if(a=='e'){printf("nnn");}
	printf("%c\t",a);
	if(b=='\n'){printf("uuu");}
	printf("%c",b);

	return 0;
}

这个程序本来应该有两次输入,但是此时输入一次程序就继续走完了:

hello
e
nnne	uuu

这说明printf缓冲区和scanf缓冲区是两个独立的缓冲区,
scanf会从缓冲区读入数据,但\n留在了缓冲区,
printf会向缓冲区写入数据,且\n会留在缓冲区作为换行符。

cin会从缓冲区读入数据,直到空白,但会忽略开头的空白,且\n会留在缓冲区;
cout会向缓冲区写入数据,且\n会留在缓冲区作为换行符。

所以输入输出都会将\n留在缓冲区,只是读入时,遇到\n代表换行,
\n是一种控制符,代表换行;
在输入时,scanf将换行符\n作为空白符对待,cin将换行符\n作为空白符对待,getline将\n作为行信息获取一行;
在输出时,\n就是作为换行符,指导设备换行显示信息。

解决方案:
在%c前边加个空格,这种格式可以忽略前边的空白字符(空格、tab):

#include<stdio.h>

int main()
{
	char a=' ';
	printf("hello\n");

	scanf("%c",&a);
	scanf(" %c",&a);

	if(a==' ') printf("a=%c\n",a);
	else printf("a=%c\n",a);

	return 0;
}
hello
e
r
a=r
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

多弗朗强哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值