scanf、printf使用详解
scanf
函数原型
#include <stdio.h>
int scanf(const char *format, ...);
参数:
-
format
:字符串参数,包含三种类型-
空白字符:它们与输入的零个或多个空白字符匹配,在处理中常被忽略
-
int num1 = 0; int num2 = 0; scanf("%d %d", &num1, &num2); // 此时scanf中有7个空白字符(空白字符不仅仅是空格,还可以是制表符、回车符) // 但在实际输入中输入1个或多个空白字符都是可以正确读取的 // 至少要有一个空白字符是要分开两个数字,否则会被当成一个数字
-
-
格式代码:它们指定函数如何解释接下来的输入字符
-
// 同样的二进制数,不同的解释就会有不同的结果 // 八位二进制数:1000 0001 // 有符号数: -1 // 无符号数: 129 printf("%d\n", -1); printf("%u\n", -1);
-
-
其他字符:当其他字符出现在格式字符串时,下一个输入字符必须与它匹配
-
如果匹配,该输入字符随后被丢弃
-
如果不匹配,函数就不再读取而是直接返回
-
int num1 = 0; int num2 = 0; scanf("请输入第一个数字:%d,请输入第二个数字:%d", &num1, &num2); // 如果在终端输入形式如下: 12 31 // 那么此时scanf会直接返回,并不会将两个数字读取到num1、num2 // 正确的输入形式应是: 请输入第一个数字:12,请输入第二个数字:31 // 这样scanf才能正确的读取
-
-
-
...
:表示一个可变长度的指针列表- 从输入转化而来的值逐个存储到这些指针参数所指向的内存
- 由此可见,
scanf
参数前面为什么要加&
符号就比较清楚了 - 如果没加
&
符号,将变量的值传递给函数,而scanf
函数却把它解释为一个指针- 当它被解引用将数据写入时,要么导致程序终止,要么导致一个不可预料的内存位置的数据被改写
- 由此可见,
- 从输入转化而来的值逐个存储到这些指针参数所指向的内存
返回值:
当格式化字符串到达末尾或者读取的输入不再匹配格式字符所指定的类型时,输入就停止。
- 被转化的输入的数目作为函数的返回值
- 如果在任何输入值被转换之前文件就已经到达末尾,函数就返回常量值EOF
- EOF是常量值-1,与ASCII中字符都不相同,这是为了避免二进制被错误解释为EOF
scanf的格式控制
格式字符串的形式为:
%[可读取的最大宽度][限定符]类型
%[width][modifiers]type
width
width(宽度,可选)是一个数值,用于指定当前读取操作中读取的最大字符数。
int num = 0;
scanf("%3d", &num);
// 如果在终端输入1002,num最多只能读取三个字符,所以num的值为100
modifiers
格式代码 | h | l | L |
---|---|---|---|
d、i、n | short | long | |
o、u、x | unsigned short | unsigned long | |
e、f、g | double | long double |
限定符的主要目的是为了指定参数的长度。如果整形参数比缺省的整形参数更短或更长,在格式代码中省略限定符就是一个常见的错误。浮点类型也是如此。
如果省略了限定符,可能会导致一个较长变量只有一部分被初始化,或者一个较短变量的相邻内存也被修改。
double dNum = 0.0;
long double ldNum = 0.0;
// 如果只使用%f,那么就会导致有一部分没被初始化
scanf("%lf", &dNum);
scanf("%Lf", &ldNum);
short int sNum = 0;
// 如果只使用%d,那么就会导致相邻内存被非法修改,这极有可能导致进程崩溃
scanf("%hd", &sNum);
各种数据类型占用空间大小
数据类型 | 占用内存(32位) | 占用内存(64位) |
---|---|---|
char | 1 | 1 |
unsigned char | 1 | 1 |
short | 2 | 2 |
unsigned short | 2 | 2 |
int | 4 | 4 |
unsigned int | 4 | 4 |
long | 4 | 8 |
unsigned long | 4 | 8 |
float | 4 | 4 |
double | 8 | 8 |
type
type(转换字符,必选)的内容及含义如下:
转换字符 | 参数类型 | 含义 |
---|---|---|
c | char* | 读取单个字符。如果给出宽度,就读取这个数目的字符 |
i | int* | 根据前缀决定基数,可以是八进制(前缀0)、十进制、十六进制(前缀0x)有符号整数 |
d | int* | 十进制有符号整数 |
u、o、x | unsigned int* | 无符号整数。u被解释为十进制、o被解释为八进制、x被解释为十六进制 |
f、e、E、g、G | float* | 浮点型字面值常量。但小数点不是必须的,也可以使用指数形式(大小写没有区别) |
s | char* | 读取一串非空字符串 |
p | void* | 读取一个指针(即内存地址) |
n | int* | 到目前为止通过调用scanf函数从输入读取的字符数被返回,%n转换的字符并不在计算scanf函数的返回值之内,它本身不消耗任何输出 |
% | (无) | 两个%%就是%本身,与输入的%相匹配 |
int num = 0;
int num1 = 0;
int num2 = 0;
scanf("%d %d%n", &num1, &num2, &num);
printf("%d\n", num);
// 若在终端输入10 02
// 那么num的值为7,因为中间输入的三个空格也是scanf读取到的字符
printf
函数原型
#include <stdio.h>
int printf(const char *format, ...);
参数:
format
:字符串参数,包含二种类型- 格式代码:指定转换的执行方式
- 其他字符:原样逐字打印
...
:用于转换的参数列表
返回值:
如果函数调用成功,返回值是实际打印的字符数(不包含表示字符串结束的 ‘\0’);
如果函数调用失败,返回值是一个负数。
printf的格式控制
格式字符串的形式为:
%[标志][输出最小宽度][.精度][修改符]类型
%[flags][width][.precision][modifiers]type
flags
flags可同时出现多个,且无顺序要求。
标志 | 含义 |
---|---|
- | 指定被转换的参数在其字段内左对齐(默认是右对齐) |
+ | 指定在输出的数前面加上正负号 |
空格 | 如果第一个字符不是正负号,则在其前面加上一个空 |
0 | 对于数值转换,当输出长度小于字段宽度时,添加前导0进行填充 |
# | 指定下表的另一种输出形式 |
用于 | #标志 |
---|---|
o | 保证产生的值以一个零开头 |
x、X | 在非零值前加0x前缀(%X则为0X) |
e、E、f | 确保结果始终包含一个小数点,即使后面没有数字 |
g、G | 确保结果始终包含一个小数点,即使后面没有数字。另外,后缀的0并不会从小数中去除 |
width
width(宽度,可选)是一个数值,用于指定要输出的最小字符数。
转换后的参数输出宽度至少要达到这个数值。如果参数的字符数小于该数值,则在参数左边填充字符(默认是空格)。
- 如果flags设置为
-
,要求参数左对齐的话则在右边填充
.precision
.precision(.精度,可选),通过点号分隔字段的宽度和精度。
- 对于字符串,它指定打印的字符的最大个数
- 对于整数,它指定打印的数字的最小位数
- 必要时可填充0以达到位数要求
- 对于转换字符为 e、E 或 f,它指定小数点后打印的数字位数
- 会发生进位
- 必要时可填充0以达到位数要求
- 对于转换字符为 g 或 G,它指定打印的有效数字位数
- 会发生进位
modifiers
- hh表示将相应的参数按
signed char/unsigned char
类型输出 - h表示将相应的参数按
short/unsigned short
类型输出 - l表示将相应的参数按
long/unsigned long
类型输出 - ll表示将相应的参数按
long long/unsigned long long
类型输出 - L表示将相应的参数按
long double
类型输出- 仅适用于浮点数说明符,上面仅适用于整数说明符
type
type(转换字符,必选)的内容及含义如下:
转换字符 | 参数类型 | 含义 |
---|---|---|
c | int | 参数被裁剪为unsigned char类型并作为字符打印 |
d、i | int | 参数作为有符号十进制整数打印 |
u、o、x、X | unsigned int | 参数作为无符号值打印。u使用十进制;o使用八进制;x或X使用十六进制(两者的区别是:x使用小写字母,X使用大写字母) |
e、E | double | 参数以指数形式输出单、双精度浮点数。小数点后面的位数由精度字段决定,默认是6(两者的区别是:打印时e的大小写) |
f | double | 参数按照常规的浮点数形式打印。小数点后面的位数由精度字段决定,默认是6 |
g、G | double | 参数以%f或%e中较短的输出宽度输出单、双精度浮点数 |
s | char* | 打印一个字符串 |
n | int* | 不产生任何输出,到目前为止函数所产生的输出字符数目将被保存到对应的参数中 |
% | (无) | 打印一个%字符 |
注:如果 % 后边的字符不是转换字符,则其行为没有定义。