printf和scanf的作用是程序和外设进行交互的接口,
printf可以将程序输出到屏幕上或打印机上;
scanf可以将键盘的字符输入到程序中;
但是printf和scanf并不是让程序和外设直接交互的,因为直接交互的话,一是外设读写速度慢,而是频繁读写外设易造成损伤,
因此在程序和外设之间,c语言在内存中增加了输入缓冲区和输出缓冲区,用于提高程序和外设读写的响应速度,详情见下文。
printf的作用是在程序中输出指定内容到设备上:
printf("hello world!\n");
| 命令 | 功能 |
|---|---|
| %d | 十进制有符号整数 |
| %u | 十进制无符号整数 |
| %f | 浮点数 |
| %s | 字符串 |
| %c | 单个字符 |
| %p | 指针的值 |
| %e | 指数形式的浮点数 |
| %x, %X | 无符号以十六进制表示的整数 |
| %o | 无符号以八进制表示的整数 |
| %g | 把输出的值按照%e或者%f类型中输出长度较小的方式输出 |
| %p | 输出地址符 |
| %lu | 32位无符号整数 |
| %llu | 64位无符号整数 |
| 命令 | 功能 |
|---|---|
| \n | 换行 |
| \f | 清屏并换页 |
| \r | 回车 |
| \t | Tab符 |
| \xhh | 表示一个ASCII码用16进表示 |
# include
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.程序结束 #includesleep(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的语句中含有\n,回车符号也会记录在缓冲区,但是printf不会输出\n字符,scanf也不会读入\n字符,因此\n字符一直留在缓冲区,
因此在使用scanf输入前,如果不想读取\n字符,就需要处理一下:
例如:
#include
int main()
{
char a=' ';
printf("hello\n");
scanf("%c",&a); //第一次输入,此时会读区printf里留下的\n,而直接略过;
scanf("%c",&a); //第二次输入,正常输入e
if(a==' ') printf("a=%c\n",a);
else printf("a=%c\n",a);
return 0;
}
这个程序本来应该有两次输入,但是此时输入一次程序就继续走完了:
hello
e
a=
解决方案:
在%c前边加个空格,这种格式可以忽略前边的空白字符(空格、tab):
#include
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