目录
1. 占位符列举
我会标出常用的占位符,红色和绿色是需要注意的要点,紫色是比较特殊但不太重要的要点
1.1 整型
1. int型:
- %d :⼗进制整数。
- %o :⼋进制整数。(提醒一下,这个是字母o,不是数字0,下面的八进制也是如此)
- %x :⼗六进制整数。
- %X:与%x一样,不过字母都是大写。
unsigned int型 --- %u :十进制无符号整数。
2. short型:
- %hd :⼗进制 short int 类型。
- %ho :⼋进制 short int 类型。
- %hx :⼗六进制 short int 类型。
- %hX:与%hx一样,不过字母都是大写。
unsigned short型 --- %hu :十进制无符号短整数。
3. long型:
- %ld :⼗进制 long int 类型。
- %lo :⼋进制 long int 类型。
- %lx :⼗六进制 long int 类型。
- %lX: 与%lx一样,不过字母都是大写。
unsigned long型 --- %lu:十进制无符号长整数。
4. long long型:
- %lld :⼗进制 long long int 类型。
- %llo :⼋进制 long long int 类型。
- %llx :⼗六进制 long long int 类型。
- %llX: 与%llx一样,不过字母都是大写。
unsigned long long型 --- %llu:十进制无符号长长整数。
5. 其他:
- %i :整数,基本等同于 %d 。
- %zd : size_t 类型整数。
- %ld :⼗进制 long int 类型,同时也用于clock_t 类型。
1.2 浮点型
1.常用
- %f :float 类型小数。
- %lf :double 类型小数。
- %Lf :long double 类型小数。
2. 其他
- %a :⼗六进制浮点数,字⺟输出为⼩写。
- %A :与%a一样,字⺟输出为⼤写。
- %e :使⽤科学计数法的浮点数,指数部分的 e 为⼩写。
- %E :与%e一样,指数部分的 E 为⼤写。
- %g :6个有效数字的浮点数。整数部分⼀旦超过6位,就会⾃动转为科学计数法,指数部分的 e为小写;而且去掉的位数会约去,逢5进1。
- %G :等同于 %g ,唯⼀的区别是指数部分的 E 为⼤写。
这里给你们演示一下有什么不同(16进制浮点数看不懂的不要紧的):
int main()
{
float f = 100500.57;
printf("%f\n", f);
printf("%a 与 %A\n", f, f);
printf("%e 与 %E\n", f, f);
printf("%g 与 %G\n", f, f);
return 0;
}
1.3 字符型
- %c :char型字符(unsigned char也适用)。
- %lc:wchar_t型宽字符。
1.4 其他种类
- %p :以十六进制打印地址。(只能用于printf )
- %s :字符串。
- %[] :遇到不在方括号之中的字符,匹配将会停⽌。(仅用于scnaf,下面会详细说)
- %*:并不是一个有效占位符,要与其他占位符结合形成赋值忽略符。(仅用于scnaf,下面会详细说)
- %% :输出⼀个百分号%。(只用于printf,用法类似转义字符“ \\ ”。如果要复习转义字符的知识点可以看一下这篇博客《转义字符的详细介绍》 )
- %n:已输出的字符串数量。该占位符本⾝不输出,只将值存储在指定变量之中。(只用于printf)
这个你们看看就好,因为容易出现bug,VS已经禁用%n这种格式了。
2. 组合型占位符与printf输出
printf() 可以定制占位符的输出格式。
2.1 限制宽度
printf() 允许限定占位符的最小宽度。
2.1.1 默认右对齐
下面示例中, %4d表示这个占位符的最小宽度为4格。如果不满4位,会在占位符对应值的前面添加空格。输出的值默认是右对⻬,即输出内容前⾯会有空格。
如果对应值的宽度超出最小宽度,那么有多少格就输出多少格,如下:
这个用法不仅能用于整数(%数字d)的打印,还能用浮点数(%数字f)、字符(%数字c)和字符串(%数字s)的打印。以字符串举例,如:
2.1.2 左对齐
如果希望在输出内容后面添加空格,改成左对齐的话,可以在占位符的 % 的后⾯插⼊⼀个 - 号。
如果对应值的宽度超出最小宽度,也是输出全部,如下:
同样的,这个用法不仅能用于整数(%-数字d)的打印,还能用浮点数(%-数字f )、字符(%-数字c)和字符串(%-数字s)的打印。以字符串举例,如:
2.2 总是显示正负号:%+d
默认情况下, printf 不对正数显示+号,只对负数显示 - 号。如果想让正数输出 + 号,可 以在占位符的 % 后⾯加⼀个“+” 。
上⾯⽰例中,%+d 可以确保输出的数值,总是带有正负号。这个方法也适用于浮点数(%+f ),如下:
因为只有数字有正负之分,所以不适用于字符和字符串。
“显示正号” 这一功能对于 左右对齐 是没有任何影响的。在右对齐中,输出的 + 号会消耗一格位置;在左对齐中,即使 + 和 - 的前后位置不同,输出的结果是相同的。
2.3 限定小数位数:%.数字f
我们可以通过%.数字f 来实现限定小数的输出位数,其中该占位符是数字代表输出位数。
通常是逢五进一。
希望小数点后⾯只保留两位,占位符可以写 成%.2f ,如下:
这种写法可以与限定宽度占位符结合使⽤(%数字. 数字f )。
如下:
2.3 输出字符串的部分字符:%.数字s
与限制小数位数类似,%.数字s 可以限制字符串的输出位数,其中数字对应输出的字符个数。(空格也占用一个字符)
同样的,这种用法也可以与限制宽度搭配使用(%数字. 数字s)
例如:
3. 组合型占位符与scanf读入
scnaf 函数也能定制占位符的输入格式
3.1 限制字符串的读入:%数字s
与printf 限制字符串输出不同,该占位符没有符号“ . ” 。作用是限定读⼊字符串的最长长度,但是遇到空白字符还是会停止读取。
3.2 扫描字符集合占位符:%[ ]
占位符%[ ] :其实使用%[ ],也是读入一个字符串。但是输入的时候,会把不在方括号[ ]规定内的字符当做空白字符,而读到空白字符时 scanf 就会停止读入。
连接符“ - ”:可以连接两个规定符号形成规定范围。比如%[0-3],这规定了输入的字符只能在集合{ 0,1,2,3 }中,其他的字符一律当做空白字符。
3.2.1 例子
### 例子1:输入只含有数字字符的字符串:%[0-9]
int main()
{
char str[50];
printf("请输入一个数字组成的字符串:");
scanf("%[0-9]", str); // 只读取数字组成的字符串
printf("您输入的数字字符串是:%s", str);
return 0;
}
输入结果:
这里输入了“456145das54651”,但是此时字母已经是空白字符,所以scanf真正读到的是“456145”。
错误种类1:输入的第一个就是空白字符(即非规定内的字符),str 什么都没有接收,打印的结果是一堆乱码。如下:
解决办法:要确保自己输入的字符是在规定范围内的。
错误种类2:使用连接符“-”的时,两个操作数与连接符隔了空格。如下:
错误代码:
int main()
{
char str[50];
printf("请输入一个数字组成的字符串:");
scanf("%[0 - 9]", str);
printf("您输入的数字字符串是:%s", str);
return 0;
}
为什么读到6就不读了?因为此时的占位符是%[0 - 9],“0”和“-”有个空格,“9”和“-”也有个空格,所以规定的真正范围是{0, ,9}这3种字符。
解决办法:规定字符与连接符“-”之间不要有空格。
### 例子2:输入只由字母组成的字符串:%[a-zA-Z]
int main()
{
char str[50];
printf("请输入一个字母组成的字符串:");
scanf("%[a-zA-Z]", str); // 只读取字母组成的字符串
printf("您输入的字符串是:%s", str);
return 0;
}
输入结果:
这里数字已经被作为空白字符了,所以只读入“AADASawdasf”。
注意:不同区段直接不要用空格隔开,如果用空格隔开,那么空格键也会被算入规定范围。
3.2.2 输入键盘上所有可显示字符
我们从上面的例子可以发现,如果方括号[ ]内有空格,那么空格就不再被认为是空白字符了。如果我们以ascii码最后一个字符为范围的终点,那么我们几乎可以输入键盘上所有可显示的字符。
查看ascii码表我们发现,第一个可打印的字符是空格,最后一个符号是~,所以我们只需要把终点设为~,即%[ -~] :
int main()
{
char str[50];
printf("请输入一个字符串:");
scanf("%[ -~]", str);
printf("您输入的字符串是:%s", str);
return 0;
}
当然,里面有些中文符号和文字是无法被读入的。
3.3 赋值忽略符:%*c
有时,⽤户的输⼊可能不符合预定的格式。
int main()
{
int year = 0;
int month = 0;
int day = 0;
scanf("%d-%d-%d", &year, &month, &day);
printf("%d %d %d\n", year, month, day);
return 0;
}
上⾯⽰例中,如果⽤户输入2020-01-01 ,就能正确解读出年⽉⽇。问题是用户可能输⼊其他格式,⽐如输入2020/01/01 ,这种情况下, scanf() 解析数据就会失败。
为了避免这种情况, scanf 提供了⼀个赋值忽略符 * 。 只要把 * 加在任何占位符的百分号后⾯,该占位符就不会返回值,解析后将被丢弃。
int main()
{
int year = 0;
int month = 0;
int day = 0;
scanf("%d%*c%d%*c%d", &year, &month, &day);
printf("%d年%d月%d日", year, month, day);
return 0;
}
现在无论客户输入“xxxx/xx/xx”,还是“xxxx xx xx” ,还是“xxxx-xx-xx” ,最终都能正确解读。加⼊了赋值忽略符 * ,表示这个占位符没有对应的变量,解读后不必返回。
单单一个%* 并不是一个合法的占位符,它需要和其他占位符组合起来使用。如:
int main()
{
int a;
scanf("%*d", &a); // 读取一个整数,但不将其存储到变量a中
char c;
scanf("%*c", &c); // 读取一个字符,但不将其存储到变量c中
float f;
scanf("%*f", &f); // 读取一个浮点数,但不将其存储到变量f中
char str[10];
scanf("%*s", str); // 读取一个字符串,但不将其存储到数组str中
return 0;
}
4. 补充(可能会更新)
更新1: %#x和%#o
%#x
:表示以十六进制形式输出整数,并在十六进制数前加上0x
前缀。%#o
:表示以八进制形式输出整数,并在八进制数前加上0
前缀。
代码演示:与%x,%o的区别
int main()
{
printf("%x %#x\n", 30, 30);
printf("%o %#o\n", 30, 30);
return 0;
}
本期博客的分享已经结束,你们对我的内容满意吗?如果觉得还ok的话,不要吝啬您的点赞哦Thanks♪(・ω・)ノ