与scanf类似,printf大概是每个C语言开发者使用的第一个函数,除了打印Hello World只剩下应付C语言上机作业或者算法比赛或考试了,这篇文章将继续温故知新,或者说带你了解一些从来没有注意过的printf的特性。
- printf的输出格式
- 从一个简单的示例开始
- 有用但少有人用的选项
-
- 指定宽度方式
- 指定精度方式
- 四种标志字符
-
- 使用示例1: -的使用
- 使用示例2: +和空格
- 使用示例3: #的使用
- 常见问题
可以进行进制输入输出的传话,比如示例代码如下
#include int main() { int num=0; while (scanf("%d",&num) != EOF) { printf("[o: %o]\n",num); printf("[o: %#o]\n",num); printf("[x: %x]\n",num); printf("[x: %#x]\n",num); printf("[x: %X]\n",num); printf("[x: %#X]\n",num); } return 0; }
printf自带进制转换功能,主要包括8进制和16进制,但是没有提供二进制的转换方式,比如输入10进制的数字15,看一下各种八进制和十六进制显示的状况详细如下:
15 [o: 17] [o: 017] [x: f] [x: 0xf] [x: F] [x: 0XF]有用但少有人用的选项
用的最多的printf的格式化控制符大概可能是%d、%c和%s,而实际printf的格式化控制符号的完整形式如下所示:
格式化控制符号形式:%[标志字符][宽度][.精度]类型
其中类型为必须,这里不再赘述,接下来通示例来确认说明剩下几种选项的使用方式。
指定宽度方式宽度非常容易理解,参看一下如下的示例代码和输出就会明白
#include int main() { printf("%9s %9s\n","Hello","LiuMiaoCN"); printf("%9s %9s\n","konitiwa","Michael"); printf("%9s %9s\n","nice to meet you","Michael"); return 0; }
输出结果为, 可以看到这种方式之下输出控制非常方便,默认右端对齐
Hello LiuMiaoCN konitiwa Michael nice to meet you Michael
宽度的设定有如下基础知识点,非常容易记忆与理解:
- 默认右端对齐
- 输出长度不足时,缺省使用空格填充
- 长度超出时,宽度设定不再起作用,不会截断输出
精度一般来说是针对浮点型的小数来设定,当小数部分的长度大于设定的精度长度时,按四舍五入方式舍去,如果小数部分小于设定的精度长度时,后面会补0。
- 对于整型变量缺省动作为:长度小于时,左侧补0,大于时没有影响
- 对于字符串变量缺省动作:长度小于时,没有影响,大于时右侧截断
详细参看如下示例则可非常清晰地理解:
- 示例代码
#include int main() { float f1=1.4567, f2=2.2; int i1=1, i2=5678; printf("[%.3f] [%.3f]\n",f1,f2); printf("[%.3d] [%.3d]\n",i1,i2); printf("[%.3s] [%.3s]\n","CN", "LiuMiao"); return 0; }
- 执行结果
[1.457] [2.200] [001] [5678] [CN] [Liu]四种标志字符
标志字符主要有-、+、#和空格四种,主要使用方法如下所示:
标志字符 使用方法 - 用于控制对齐方式,默认为右对其,如果使用-标志字符,说明将对其方式设定为左对齐。 + 用于控制整数或者浮点数的输出符号,缺省只有负数才会输出符号,如果使用+标志字符,正数也会输出符号+。 空格 用于控制整数或者浮点数的输出符号,缺省只有负数才会输出符号,与+不同,正数前显示为空格,负数前才输出-,一般对齐的时候很有用。 # 对于控制八进制(%o)和十六进制(%x / %X)的显示前缀,注意X和x的原因在于十六进制存在A-F六个字母,所以x或者X表示这个六个字母的大小写设定,而八进制的前缀为0,数字不存在大小写的概念,自然没有O的选项。 使用示例1: -的使用一般结合宽度的设定,比如使用如下代码执行一下就可以看的非常清楚
#include int main() { printf("%9s %9s\n","Hello","LiuMiaoCN"); printf("%9s %9s\n","konitiwa","Michael"); printf("%-9s %-9s\n","Hello","LiuMiaoCN"); printf("%-9s %-9s\n","konitiwa","Michael"); return 0; }
执行结果:
Hello LiuMiaoCN konitiwa Michael Hello LiuMiaoCN konitiwa Michael使用示例2: +和空格
- 示例代码
#include int main() { printf("[%9d] [%9d]\n",1024,-1024); printf("[%+9d] [%+9d]\n",1024,-1024); printf("[% 9d] [% 9d]\n",1024,-1024); printf("[%d] [%d]\n",1024,-1024); printf("[% d] [% d]\n",1024,-1024); return 0; }
- 执行结果
[ 1024] [ -1024] [ +1024] [ -1024] [ 1024] [ -1024] [1024] [-1024] [ 1024] [-1024]使用示例3: #的使用
八进制和十六进制的前缀的使用前文已经介绍,这里对小数来使用一下确认效果
- 示例代码
#include int main() { printf("[%9d] [%9d]\n",1024,-1024); printf("[%+9d] [%+9d]\n",1024,-1024); printf("[% 9d] [% 9d]\n",1024,-1024); printf("[%d] [%d]\n",1024,-1024); printf("[% d] [% d]\n",1024,-1024); return 0; }
- 执行结果
[ 1024] [ -1024] [ +1024] [ -1024] [ 1024] [ -1024] [1024] [-1024] [ 1024] [-1024]常见问题
缓冲区相关的现象,比如如下示例代码
#include #include int main() { printf("hello "); sleep(10); printf(" liumiaocn\n"); return 0; }
咋一看应该是先输出hello ,然后等10秒之后输出 liumiaocn,然后换行,而实际是之前什么也不输出,上来就是sleep 10秒,然后输出hello liumiaocn换行后退出了。实际这里面是有个缓冲区的, 将代码稍微修改,加上如下对于标准输出的强制输出fflush就能够理解背后的原因了
#include #include int main() { printf("hello "); fflush(stdout); sleep(10); printf(" liumiaocn\n"); return 0; }
虽然这是一个很简单的例子,突然想起来十年前写过一个简单的面试题就是以此为陷阱,结合父子进程的创建,只是简单的确认子进程和父进程的输出结果,不知道让当时多少进公司的高手骂过无耻,还好现在没有多少人用c语言了。