printf()函数是C语言标准I/O中最常用的控制台输出函数,除了我们最常见的%d,%c,%s和%f以外
printf()和%说明符还提供很多功能丰富的输出形式,以下是一个demo程序,可以复制到你的IDE运行查看结果,对照学习
【转换说明符demo程序】
#include <stdio.h>
/* \t是水平制表符,理解为tab键,\n是换行符,理解为回车键 */
int main()
{
/* %%,打印% */
printf("%%%%,打印%%\n");
printf("以下是各种%%说明符的常见使用\n\n\n");
/* %a,%A,浮点数、十六进制数和p-记数法 */
printf("%%a,%%A,浮点数、十六进制数和p-记数法\n");
printf("[3.14f]=%a\t[3.14f]=%A\n\n\n", 3.14f, 3.14f);
/* %c,打印一个字符 */
printf("%%c,打印一个字符\n");
printf("[A]=%c\t[&]=%c\n\n\n", 'A', '&');
/* %d,%i,有符号十进制整数 */
printf("%%d,%%i,有符号十进制整数\n");
printf("[1024]=%d\t[-256]=%i\n\n\n", 1024, -256);
/* %e,%E,浮点数、e-记数法和E-记数法 */
printf("%%e,%%E,浮点数、e-记数法和E-记数法\n");
printf("[3.14f]=%e\t[3.14f]=%E\n\n\n", 3.14f, 3.14f);
/* %f,浮点数、十进制记数法 */
printf("%%f,浮点数、十进制记数法\n");
printf("[3.14f]=%f\t[-3.14]=%f\n\n\n", 3.14f, -3.14);
/* %g,%G,自动选择%f格式或%e格式,指数小于-4或大于等于精度时使用%e */
printf("%%g,%%G,自动选择%%f格式或%%e格式,指数小于-4或大于等于精度时使用%%e\n");
printf("[3.14e-5]=%g\t[3.14f]=%G\n\n\n", 3.14e-5, 3.14f);
/* %o,无符号八进制数 */
printf("%%o,无符号八进制数\n");
printf("[80]=%o\t[0123]=%o\n\n\n", 80, 0123);
/* %p,指针 */
int *a;
int b = 100;
a = &b;
printf("%%p,指针\n");
printf("[a]=%p\t[&b]=%p\n\n\n", a, &b);
/* %s,字符串 */
printf("%%s,字符串\n");
printf("%s\t%s\n\n\n", "Hello world.", "你好\t世界。");
/* %u,无符号十进制整数 */
printf("%%u,无符号十进制整数\n");
printf("[123]=%u\t[-10]=%u\n\n\n", 123, -10);
/* %x,%X,无符号十六进制整数,0f或0F */
printf("%%x,%%X,无符号十六进制整数,0f或0F\n");
printf("[100]=%x\t[0x12]=%X\n\n\n", 100, 0x12);
return 0;
}
注:
1、demo程序输出结果中,[ ]内表示的是编程时书写的常量的形式,=后是输出结果
2、printf()中存在自动类型转换,如%f中对-3.14的输出,-3.14原本被系统认为是double浮点常量,但使用%f仍然是转换类型后,用float类型输出
3、printf()中存在隐式的进制转换,如%o中对十进制常量80的输出,结果为八进制数0120,显示为120,对显示的八进制常量0123输出则得到123,说明%o的显示结果是隐式的八进制数。同理%x中,对十进制常量100输出为64,其实该64应该是0x64,而0x12输出也为12,这些输出结果都是隐藏了进制的
4、printf()中对无符号整数输出时要特别注意,一定区分什么时候用%d,什么时候用%u,如%u中对-10的输出,结果是一个很大的数,这是因为计算机中有无符号数的存储方式差异造成的,有符号数把最高位看做符号位,而无符号数把所有位看做数值位,因此-10在有符号数中最高位的1,同样的内存用无符号输出则会把所有位看做数值位,所以会是一个很大的数
5、%s能识别字符串中的转义字符,如%s中的“你好\t世界”,水平制表符会被识别到,%s输出时不会显示\0结束符
printf()除了以上功能丰富的%转换说明符,还有一些增强功能的转换说明修饰符,这提供了很多很好的编程技巧
【转换说明修饰符demo程序】
#include <stdio.h>
int main(void)
{
/* -,左对齐 */
printf("-,左对齐\n");
printf("%-d\n\n\n", 12);
/* +,输出的数带符号,正负都有 */
printf("+,输出的数带符号,正负都有\n");
printf("%+f\t%+d\n\n\n", 3.14f, -1024);
/* (空格),%后留一个空格,表示有符号值为正时空格,为负时加符号 */
printf("(空格),%后留一个空格,表示有符号值为正时空格,为负时加符号\n");
printf("% f\t% e\n\n\n", 3.14f, -6.28e-4);
/* #,显式地显示进制 */
printf("#,显式地显示进制\n");
printf("%#o\t%#x\t%#\n\n\n", 0123, 0x12);
/* 0,数字格式时,用0填充字段宽度 */
printf("0,数字格式时,用0填充字段宽度\n");
printf("%010d\t%08.3f\n\n\n", 12, 3.14f);
/* 数字,说明符前加数字表示字段宽度的最小值 */
printf("数字,说明符前加数字表示字段宽度的最小值\n");
printf("%4d\t%4d\t%4d\n\n\n", 12, 1234, 123456);
/* .数字,表示精度,针对浮点数,如%8.3f表示字段长度为8,小数点后3位 */
printf(".数字,表示精度,针对浮点数,如%%8.3f表示字段长度为8,小数点后3位\n");
printf("%8.3f\t%5.2f\t%3.1f\n\n\n", 12.12345, 12.12345, 12.12345);
/* h,表示short类型 */
printf("h,表示short类型\n");
printf("%hu\t%hx\t%5.5hd\n\n\n", 1024, 0x12, 10240);
/* hh,表示char类型 */
printf("hh,表示char类型\n");
printf("%hhu\t%hhx\t%6.4hd\n\n\n", 1024, 0x12, 10240);
/* l,表示long类型 */
printf("l,表示long类型\n");
printf("%ld\t%8lu\n\n\n", -111222, 12345);
/* ll,支持long long的系统中表示long long类型 */
printf("ll,支持long long的系统中表示long long类型\n");
printf("%lld\t%8llu\n\n\n", 33334444, -123321);
/* L,表示long double类型 */
printf("L,表示long double类型\n");
printf("%Lf\t%10.4Le\n\n\n", 3.1415926, 3.1415926);
return 0;
}
注:
1、无论怎么加修饰,一定还是要注意无符号数的输出,如上述%8llu中对-123321的输出,仍然是错值,根本还是在于%u对负数输出这一常见错误
2、从demo已经能看出,修饰符是可以叠加的,如%10.3Lf就表示输出的long double数字段长度为10,精确到千分位
3、%8d、%.4f这样的控制字段长度的用法是很多算法设计大赛中很常见且很好用的技巧,有兴趣的同学可以着重练习