C语言编程中,输入输出是基本操作,printf和scanf并不是C语言中的唯一的输入输出选择,对于输入有scanf()、getchar()、getche()、getch()、gets();对于输出有printf()、puts()、putchar(),他们各有自己的使用场景,本篇文章主要介绍常用的scanf和printf
一:scanf详解
scanf 是 scan format 的缩写,意思是格式化扫描,也就是从键盘获得用户输入
1,格式化输入
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
//输入一个整数
int a;
scanf("%d",&a);
printf("a = %d\n",a);
getchar();
//输入一个字符
char b;
scanf("%c",&b);
printf("b = %c\n",b);
getchar();
//输入一个字符串
char c[10] = {0};
scanf("%s",c);
printf("c = %s\n",c);
}
运行结果:
上面的举例是scanf的基本用法,看到上面的例子有同学就有疑问了为什么两次输入之间要有getchar(),这个后面会讲到。对于scanf输入有严格的格式控制符,如下
格式控制符 | 说明 |
---|---|
%c | 读取一个单一的字符 |
%hd、%d、%ld | 读取一个十进制整数,并分别赋值给 short、int、long 类型 |
%ho、%o、%lo | 读取一个八进制整数(可带前缀也可不带),并分别赋值给 short、int、long 类型 |
%hx、%x、%lx | 读取一个十六进制整数(可带前缀也可不带),并分别赋值给 short、int、long 类型 |
%hu、%u、%lu | 读取一个无符号整数,并分别赋值给 unsigned short、unsigned int、unsigned long 类型 |
%f、%lf | 读取一个十进制形式的小数,并分别赋值给 float、double 类型 |
%e、%le | 读取一个指数形式的小数,并分别赋值给 float、double 类型 |
%g、%lg | 既可以读取一个十进制形式的小数,也可以读取一个指数形式的小数,并分别赋值给 float、double 类型 |
%s | 读取一个字符串(以空白符为结束) |
2,带空格输入到多个变量
#include <stdio.h>
#include <stdlib.h>
int main()
{
//输入一个整数
int a, b, c;
scanf("%d %d", &a, &b);
printf("a=%d, b=%d\n", a,b);
scanf("%d %d", &a, &b);
printf("a=%d, b=%d\n", a,b);
scanf("%d, %d, %d", &a, &b, &c);
printf("a=%d, b=%d, c=%d\n", a,b,c);
scanf("%d not equal %d", &a, &b);
printf("a=%d, b=%d\n", a,b);
}
运行结果:
第一个 scanf() 的格式控制字符串为"%d %d"
,中间有一个空格,而我们却输入了1 2
,中间有多个空格。第二个 scanf() 的格式控制字符串为"%d %d"
,中间有多个空格,而我们却输入了1 2,中间只有一个空格。这说明 scanf() 对输入数据之间的空格的处理比较宽松,并不要求空格数严格对应,多几个少几个无所谓,只要有空格就行。
用户每次按下回车键,程序就会认为完成了一次输入操作,scanf() 开始读取用户输入的内容,并根据格式控制字符串从中提取有效数据,只要用户输入的内容和格式控制字符串匹配,就能够正确提取。
本质上讲,用户输入的内容都是字符串,scanf() 完成的是从字符串中提取有效数据的过程
3,连续输入到数组
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a[5];
int i = 0;
for(i=0; i<5; i++)
{
scanf("%d",a+i);
}
for(i=0; i<5; i++)
{
printf("%d ",a[i]);
}
printf("\n");
}
运行结果:
4,带空格的字符串输入
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str[100];
scanf("%[^\n]",str);//以换行符作为字符串输入的结束
printf("%s\n",str);
}
运行结果:
利用格式符"%[^]",可以输入带空格的字符串到数组。需要注意的是方括号里边的^后面的字符表示的是输入的结束符,如同默认情况下空格和回车键以及TAB键是作为字符串输入的结束符一样,利用此格式符便相当于由编程者自己指定一个输入结束符。
5,刷题常用的对同一变量连续输入
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a;
while(scanf("%d",&a)!=EOF)
{
printf("a = %d\n",a);
}
}
EOF在scanf连用时代表-1的意思,当用到while(scanf()!=EOF),代表的意思是一直输入,直到scanf返回的值是-1时才会停止输入,也可以在while里面加上一些约束条件,使输入在特定的条件下就会停止,也可以在输入完成后按下Ctrl+z,可以强行停止输入
6,scanf输入的本质
从本质上讲,我们从键盘输入的数据并没有直接交给 scanf(),而是放入了缓冲区中,直到我们按下回车键,scanf() 才到缓冲区中读取数据。如果缓冲区中的数据符合 scanf() 的要求,那么就读取结束;如果不符合要求,那么就继续等待用户输入,或者干脆读取失败。
需要注意的是如果缓冲区中的数据不符合 scanf() 的要求,要么继续等待用户输入,要么就干脆读取失败。
问题回到了1章节,为什么要在每个输入后面加个getchar(),如果不加运行结果如下:
出现这种现象就是和缓冲区有关,当我们按下enter键的时候,缓冲区里是有enter的控制符,会当做第二次scanf的输入,所以需要用getchar去清除缓冲区里的enter控制符。
二:printf详解
printf() 是最灵活、最复杂、最常用的输出函数
1,printf的基本用法
printf 函数原型为int printf(const char *fmt, ...),使用了可变参数的模式
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a = 10;
char b = 'b';
float c = 9.99;
printf("%d %c %f\n",a,b,c);
}
对于基本printf的用法需要注意的是格式控制符,对变量以什么样的形式输出
格式控制符 | 说明 |
---|---|
%c | 输出一个单一的字符 |
%hd、%d、%ld | 以十进制、有符号的形式输出 short、int、long 类型的整数 |
%hu、%u、%lu | 以十进制、无符号的形式输出 short、int、long 类型的整数 |
%ho、%o、%lo | 以八进制、不带前缀、无符号的形式输出 short、int、long 类型的整数 |
%#ho、%#o、%#lo | 以八进制、带前缀、无符号的形式输出 short、int、long 类型的整数 |
%hx、%x、%lx %hX、%X、%lX | 以十六进制、不带前缀、无符号的形式输出 short、int、long 类型的整数。如果 x 小写,那么输出的十六进制数字也小写;如果 X 大写,那么输出的十六进制数字也大写。 |
%#hx、%#x、%#lx %#hX、%#X、%#lX | 以十六进制、带前缀、无符号的形式输出 short、int、long 类型的整数。如果 x 小写,那么输出的十六进制数字和前缀都小写;如果 X 大写,那么输出的十六进制数字和前缀都大写。 |
%f、%lf | 以十进制的形式输出 float、double 类型的小数 |
%e、%le %E、%lE | 以指数的形式输出 float、double 类型的小数。如果 e 小写,那么输出结果中的 e 也小写;如果 E 大写,那么输出结果中的 E 也大写。 |
%g、%lg %G、%lG | 以十进制和指数中较短的形式输出 float、double 类型的小数,并且小数部分的最后不会添加多余的 0。如果 g 小写,那么当以指数形式输出时 e 也小写;如果 G 大写,那么当以指数形式输出时 E 也大写。 |
%s | 输出一个字符串 |
2,固定宽度输出
对于要输出固定宽度并且要对齐的矩阵式数据,printf也是可以轻松搞定的
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a1=11, a2=111, a3=1111, a4=11111;
int b1=2, b2=22, b3=222, b4=2222;
int c1=33333, c2=333, c3=33, c4=3;
int d1=666666, d2=66, d3=66666, d4=6666;
printf("%-10d %-10d %-10d %-10d\n", a1, a2, a3, a4);
printf("%-10d %-10d %-10d %-10d\n", b1, b2, b3, b4);
printf("%-10d %-10d %-10d %-10d\n", c1, c2, c3, c4);
printf("%-10d %-10d %-10d %-10d\n", d1, d2, d3, d4);
}
运行结果:
printf() 格式控制符的完整形式如下
%[flag][width][.precision]type[ ] 表示此处的内容可有可无,是可以省略的。
1) type 表示输出类型,比如 %d、%f、%c、%lf,type 就分别对应 d、f、c、lf;再如,%-10d
中 type 对应 d。type 这一项必须有,这意味着输出时必须要知道是什么类型。
2) width 表示最小输出宽度,也就是至少占用几个字符的位置;例如,%-10d
中 width 对应 10,表示输出结果最少占用 9 个字符的宽度。
当输出结果的宽度不足 width 时,以空格补齐(如果没有指定对齐方式,默认会在左边补齐空格);当输出结果的宽度超过 width 时,width 不再起作用,按照数据本身的宽度来输出。
3) .precision 表示输出精度,也就是小数的位数。
- 当小数部分的位数大于 precision 时,会按照四舍五入的原则丢掉多余的数字;
- 当小数部分的位数小于 precision 时,会在后面补 0。
另外,.precision 也可以用于整数和字符串,但是功能却是相反的:
- 用于整数时,.precision 表示最小输出宽度。与 width 不同的是,整数的宽度不足时会在左边补 0,而不是补空格。
- 用于字符串时,.precision 表示最大输出宽度,或者说截取字符串。当字符串的长度大于 precision 时,会截掉多余的字符;当字符串的长度小于 precision 时,.precision 就不再起作用。
4) flag 是标志字符。例如,%#x
中 flag 对应 #,%-10d
中 flags 对应-
。下表列出了 printf() 可以用的 flag:
标志字符 | 含 义 |
---|---|
- | - 表示左对齐。如果没有,就按照默认的对齐方式,默认一般为右对齐。 |
+ | 用于整数或者小数,表示输出符号(正负号)。如果没有,那么只有负数才会输出符号。 |
空格 | 用于整数或者小数,输出值为正时冠以空格,为负时冠以负号。 |
# |
|