《小菜狗 C 语言入门 + 进阶笔记》(9)输入 & 输出语句(2)【你知道%20.15f是什么意思嘛?】

文章目录:《小菜狗 C 语言入门 + 进阶笔记》(0)简介

暂时无法在飞书文档外展示此内容

1、printf 和 scanf 的组合使用:

如之前章节(2.5)数据类型获取输入成绩信息,并打印出来:

#include                  //头文件
                                   //空白行
/* 我们的第二个 C 程序 */           //注释
int main()                         //main 函数
{                                  //函数体开始
    int score = 0;                 //变量
    printf("请输入成绩:");          //输出语句
    scanf("%d", &score);           //输入语句
    printf("成绩是:%d\n", score);  //输出语句
    return 0;                      //结束并返回语句
}                                  //函数体结束

注意:

C 语言中 printf 输出 double 和 float 都可以用 %f 占位符 可以混用,而 double 可以额外用 %lf

而 scanf 输入情况下 double 必须用 %lf,float 必须用 %f 不能混用。

2、printf() 的高级用法

2.1、对齐格式输出
2.1.1、背景

在实际开发工作中,做应用开发的小伙伴们,经常会为了增强客户的阅读性,使数据信息(数字或者字符串)对齐。

2.1.2、最简单的办法

根据编译输出一次一次的加空格调整,屏幕前的你们刚出社会,开发相关应用程序显示的时候,是不是这样干的呢?如下例子:

#include 
int main()
{
    int a1=20, a2=345, a3=700, a4=22;
    int b1=56720, b2=9999, b3=20098, b4=2;
    int c1=233, c2=205, c3=1, c4=6666;
    int d1=34, d2=0, d3=23, d4=23006783;

    printf("%d        %d       %d       %d\n", a1, a2, a3, a4);
    printf("%d     %d      %d     %d\n", b1, b2, b3, b4);
    printf("%d       %d       %d         %d\n", c1, c2, c3, c4);
    printf("%d        %d         %d        %d\n", d1, d2, d3, d4);

    return 0;
}

运行结果:

20        345       700       22
56720     9999      20098     2
233       205       1         6666
34        0         23        23006783

看,这是多么地自虐,要敲那么多空格,还要严格控制空格数,否则输出就会错位。更加恶心的是,如果数字的位数变了,空格的数目也要跟着变。例如,当 a1 的值是 20 时,它后面要敲八个空格;当 a1 的值是 1000 时,它后面就要敲六个空格。每次修改整数的值,都要考虑修改空格的数目,逼死强迫症!

2.1.3、使用占位符的标志字符

类似的需求随处可见,整齐的格式会更加美观。其实,我们大可不必像上面一样,printf() 可以更好的控制输出格式。更改上面的代码:

#include 
int main()
{
    int a1=20, a2=345, a3=700, a4=22;
    int b1=56720, b2=9999, b3=20098, b4=2;
    int c1=233, c2=205, c3=1, c4=6666;
    int d1=34, d2=0, d3=23, d4=23006783;

    printf("%-9d %-9d %-9d %-9d\n", a1, a2, a3, a4);
    printf("%-9d %-9d %-9d %-9d\n", b1, b2, b3, b4);
    printf("%-9d %-9d %-9d %-9d\n", c1, c2, c3, c4);
    printf("%-9d %-9d %-9d %-9d\n", d1, d2, d3, d4);

    return 0;
}

输出结果:

20        345       700       22
56720     9999      20098     2
233       205       1         6666
34        0         23        23006783

这样写起来更加方便,即使改变某个数字,也无需修改 printf() 语句,增加或者减少空格数目。

解释说明:

%-9d 中,d 表示以十进制输出,9 表示最少占 9 个字符的宽度,宽度不足以空格补齐,- 表示左对齐。综合起来,%-9d 表示以十进制输出,左对齐,宽度最小为 9 个字符。大家可以亲自试试 %9d 的输出效果。

**2.2、**printf() 格式控制符的完整形式
%[flag][width][.precision]type

[ ] 表示此处的内容可有可无,是可以省略的。

2.2.1、type

type 表示输出类型,比如 %d、%f、%c、%lf,type 就分别对应 d、f、c、lf;再如,%-9d中 type 对应 d。 type 这一项必须有,这意味着输出时必须要知道是什么类型。

2.2.2、[width]

width 表示最小输出宽度,也就是至少占用几个字符的位置;例如,%-9d中 width 对应 9,表示输出结果最少占用 9 个字符的宽度。

  • 当输出结果的宽度不足 width 时,以空格补齐(如果没有指定对齐方式,输出的值默认是右对⻬,即默认会在左边补齐空格);
  • 当输出结果的宽度超过 width 时,width 不再起作用,按照数据本身的宽度来输出。

width 的基本用法:

#include 
int main(){
    int n = 234;
    float f = 9.8;
    char c = '@';
    char *str = "abc";    //指针,后期讲解
    printf("%10d%12f%4c%2s", n, f, c, str);

    return 0;
}

运行结果:

       234    9.800000   @abc

对输出结果的说明:

  • n 的指定输出宽度为 10,234 的宽度为 3,所以前边要补上 7 个空格。
  • f 的指定输出宽度为 12,9.800000 的宽度为 8,所以前边要补上 4 个空格。
  • str 的指定输出宽度为 2,“abc” 的宽度为 3,超过了 2,所以指定输出宽度不再起作用,而是按照 str 的实际宽度输出。

width 的小数用法:

对于小数,这个限定符会限制所有数字的最小显示宽度。

#include 
int main()
{
    printf("%12f\n", 123.45);
    return 0;
}

运行结果:

  123.450000

对输出结果的说明:

  • %12f 表示输出的浮点数最少要占据 12 位。由于小数的默认显示精度是小数点后 6 位,所以 123.45 输出结果的头部会再添加 2 个空格
2.2.3、[.precision]

.precision 表示输出精度,也就是小数的位数

  • 当小数部分的位数大于 precision 时,会按照四舍五入的原则丢掉多余的数字;
  • 当小数部分的位数小于 precision 时,会在后面补 0。

另外,.precision 也可以用于整数和字符串,但是功能却是相反的:

  • 用于整数时,.precision 表示最小输出宽度。与 width 不同的是,整数的宽度不足时会在左边补 0,而不是补空格。
  • 用于字符串时,.precision 表示最大输出宽度,或者说截取字符串。当字符串的长度大于 precision 时,会截掉多余的字符;当字符串的长度小于 precision 时,.precision 就不再起作用。

请看下面的例子:

#include 
int main(){
    int n = 123456;
    double f = 882.923672;
    char *str = "abcdefghi";
    printf("n: %.9d  %.4d\n", n, n);
    printf("f: %.2lf  %.4lf  %.10lf\n", f, f, f);
    printf("str: %.5s  %.15s\n", str, str);
    return 0;
}

运行结果:

n: 000123456  123456
f: 882.92  882.9237  882.9236720000
str: abcde  abcdefghi

对输出结果的说明:

  • 对于 n,.precision 表示最小输出宽度。n 本身的宽度为 6,当 precision 为 9 时,大于 6,要在 n 的前面补 3 个 0;当 precision 为 4 时,小于 6,不再起作用。
  • 对于 f,.precision 表示输出精度。f 的小数部分有 6 位数字,当 precision 为 2 或者 4 时,都小于 6,要按照四舍五入的原则截断小数;当 precision 为 10 时,大于 6,要在小数的后面补四个 0。
  • 对于 str,.precision 表示最大输出宽度。str 本身的宽度为 9,当 precision 为 5 时,小于 9,要截取 str 的前 5 个字符;当 precision 为 15 时,大于 9,不再起作用。
2.2.4、[flag]

flag 是标志字符。例如,%#x 中 flag 对应 #%-9d 中 flags 对应 -。下表列出了 printf() 可以用的 flag:

标志字符 含 义
- -表示左对齐。如果没有,就按照默认的对齐方式,默认一般为右对齐。
+ 用于整数或者小数,表示输出符号(正负号)。如果没有,那么只有负数才会输出符号。
空格 用于整数或者小数,输出值为正时冠以空格,为负时冠以负号。
# 对于八进制(%o)和十六进制(%x / %X)整数,# 表示在输出时添加前缀;八进制的前缀是 0,十六进制的前缀是 0x / 0X。对于小数(%f / %e / %g),# 表示强迫输出小数点。如果没有小数部分,默认是不输出小数点的,加上 # 以后,即使没有小数部分也会带上小数点。

请看下面的例子:

include 
int main(){
    int m = 192, n = -943;
    float f = 84.342;
    printf("m=%10d, m=%-10d\n", m, m);  //演示 - 的用法
    printf("m=%+d, n=%+d\n", m, n);  //演示 + 的用法
    printf("m=% d, n=% d\n", m, n);  //演示空格的用法
    printf("f=%.0f, f=%#.0f\n", f, f);  //演示#的用法

    return 0;
}

运行结果:

m=       192, m=192      
m=+192, n=-943
m= 192, n=-943
f=84, f=84.

对输出结果的说明:

  • 当以%10d输出 m 时,是右对齐,所以在 192 前面补七个空格;当以%-10d输出 m 时,是左对齐,所以在 192 后面补七个空格。
  • m 是正数,以%+d输出时要带上正号;n 是负数,以%+d输出时要带上负号。
  • m 是正数,以% d输出时要在前面加空格;n 是负数,以% d输出时要在前面加负号。
  • %.0f表示保留 0 位小数,也就是只输出整数部分,不输出小数部分。默认情况下,这种输出形式是不带小数点的,但是如果有了#标志,那么就要在整数的后面“硬加上”一个小数点,以和纯整数区分开。
2.3、[width] [.precision] 的结合使用

小数指定数据宽度小数位数,用 %m.nf

双精度变量 a 输出 15 位小数,用 %20.15f 的格式声明,指定输出的数据占 20 列,其中包括 15 位小数。

请看下面的例子:

#include
int main()
{
    double a=1.0;
    printf("%20.15f\n",a/3);
    return 0;
}

运行结果:

   0.333333333333333

对输出结果的说明:

  • 注意在 0 的前面有 3 个空格,且双精度数只保证 15 位有效数字的准确性。
2.3.1、【扩展】

最小宽度和小数位数这两个限定值,都可以用 * 代替,通过 printf() 的参数传⼊。

#include 
int main()
{
    printf("%*.*f\n", 6, 2, 0.5);
    return 0;
}

运行结果:

  0.50

对输出结果的说明:

  • 等同于 printf("%6.2f\n", 0.5);
  • %*.*f 的两个星号通过 printf() 的两个参数 6 和 2 传⼊。
2.4、【拓展】%ds, %% 类型解析

%d 输出整数,%s 输出字符串,那么 %ds 输出什么呢?

#include 
int main()
{
    int a=1234;
    printf("a=%ds\n", a);

    return 0;
}

运行结果:

a=1234s

从输出结果可以发现,%d 被替换成了变量 a 的值,而 s 没有变,原样输出了。

这是因为:

%d 才是格式控制符,%ds 在一起没有意义,s 仅仅是跟在 %d 后面的一个普通字符,所以会原样输出。

文章目录:《小菜狗 C 语言入门 + 进阶笔记》(0)简介

每日一更!

公众号、CSDN等博客:小菜狗编程笔记

谢谢点赞关注哈!目前在飞书持续优化更新~

日更较慢有需要完整笔记请私我,C/C++/数据结构-算法/单片机51-STM32-GD32-ESP32/嵌入式/Linux操作系统/uboot/Linux内核-驱动-应用/硬件入门-PCB-layout/Python/后期小程序和机器学习!

你可能感兴趣的:(《小菜狗,C,语言入门,+,进阶笔记》,c语言,笔记,开发语言,C语言程序设计,青少年编程,c++,printf)