Kodewick
第 3 课,共 30 课目录

输出和输入

第 3 课,共 30 课 · 第 1 部分 · 起步 · 约 15 分钟

第 2 课里,%f 总是显示 6 位小数,价格 4.5 显示成 4.500000,没人这样写价格。这一课先学怎么让输出整齐好看,再学怎么让程序读入用户输入的数。

main.c
1#include <stdio.h>2 3int main(void) {4    double price = 3.5;5    printf("%f\n", price);6    printf("%.2f\n", price);7    return 0;8}
输出
3.500000
3.50

小数位

在 % 和 f 中间写 .2,就只显示两位小数;.1 是一位,.0 是不要小数。多出来的位数会四舍五入:

main.c
1#include <stdio.h>2 3int main(void) {4    double temp = 36.678;5    printf("%.2f\n", temp);6    printf("%.1f\n", temp);7    printf("%.0f\n", temp);8    printf("%f\n", temp);9    return 0;10}
输出
36.68
36.7
37
36.678000

这只改变显示出来的样子。变量 temp 里的值还是 36.678,最后一行就能看出来。

宽度和对齐

在 % 后面写一个数,是宽度:这个值至少占这么多个字符,不够的话在前面补空格,数就靠右对齐了。方括号是为了看清空格:

main.c
1#include <stdio.h>2 3int main(void) {4    printf("[%5d]\n", 42);5    printf("[%5d]\n", 1234);6    printf("[%5d]\n", 123456);7    return 0;8}
输出
[   42]
[ 1234]
[123456]

123456 有 6 位,比宽度还长,就照原样全部显示,一位也不会少。宽度前面加一个减号,又会怎样?

先猜一猜

这段程序显示什么?

1#include <stdio.h>2 3int main(void) {4    printf("[%-5d]\n", 42);5    return 0;6}

宽度和小数位可以一起用。%8.2f 是至少 8 个字符、两位小数。一列数字这样对齐,小数点就上下对齐了:

main.c
1#include <stdio.h>2 3int main(void) {4    printf("%-4d%8.2f\n", 1, 3.5);5    printf("%-4d%8.2f\n", 2, 12.25);6    printf("%-4d%8.2f\n", 3, 108.0);7    return 0;8}
输出
1       3.50
2      12.25
3     108.00
写法意思显示成
[%d] 配 42照原样[42]
[%5d] 配 42至少 5 个字符,靠右[ 42]
[%-5d] 配 42至少 5 个字符,靠左[42 ]
[%.2f] 配 3.14159两位小数[3.14]
[%8.2f] 配 3.14159至少 8 个字符,两位小数[ 3.14]

显示 % 本身

% 在 printf 里是格式符的开头。要显示一个真正的百分号,就写两个:%%。

main.c
1#include <stdio.h>2 3int main(void) {4    int done = 75;5    double rate = 2.5;6    printf("完成了 %d%%\n", done);7    printf("年利率:%.1f%%\n", rate);8    return 0;9}
输出
完成了 75%
年利率:2.5%

用 scanf 读一个数

printf 往外显示,scanf 往里读:它等用户输入,再把读到的值放进变量。点运行,输入一个数试试;页面上显示的是有人输入 25 时的样子(输入的内容本身不显示)。

main.c
1#include <stdio.h>2 3int main(void) {4    int age;5    printf("你多大了?\n");6    scanf("%d", &age);7    printf("你今年 %d 岁\n", age);8    return 0;9}
输出
你多大了?
你今年 25 岁

scanf("%d", &age) 里的 %d 说要读一个整数,&age 说读到的数放进 age。注意变量名前面的 &:scanf 要知道变量在内存里的哪个位置,才能往里放。为什么是这样,第 15 课再讲;现在只要记住:scanf 里的变量前面写 &,printf 里不写。

小技巧: 忘了写 & 是用 scanf 时最常见的错。编译器一般会给一条警告,警告也要看。

一次读几个值

和 printf 一样,一个 scanf 可以有好几个格式符,后面的变量按顺序对上:

main.c
1#include <stdio.h>2 3int main(void) {4    int width;5    int height;6    printf("输入宽和高:\n");7    scanf("%d %d", &width, &height);8    printf("宽 %d,高 %d\n", width, height);9    return 0;10}
输出
输入宽和高:
宽 3,高 4

用户可以输入 3 4 再回车,也可以 3 回车、4 回车:%d 会跳过前面的空格和换行,去找下一个数。

读小数用 %lf

读 double 时,scanf 要写 %lf(l 是 long 的第一个字母),不是 %f。显示的时候 printf 照样用 %f:

main.c
1#include <stdio.h>2 3int main(void) {4    double price;5    printf("价格是多少?\n");6    scanf("%lf", &price);7    printf("价格:%.2f\n", price);8    return 0;9}
输出
价格是多少?
价格:19.90
类型printf 显示scanf 读入
int%d%d
double%f%lf

scanf 的返回值

用户什么都可能输入。scanf 做完以后会给出一个数:成功读到了几个值。把它存进变量看看,假设用户输入的是 abc:

main.c
1#include <stdio.h>2 3int main(void) {4    int count = 0;5    int n = scanf("%d", &count);6    printf("读到了 %d 个数\n", n);7    printf("count 还是 %d\n", count);8    return 0;9}
输出
读到了 0 个数
count 还是 0

abc 不是整数,所以一个也没读到,n 是 0,count 也没被改。现在知道有这么回事就行;学了 if(第 5 课)以后,就能用它检查用户是不是真的输入了数字。

练一练

写好代码,点检查。提示随便看,实在想不出来再看答案。

练习 1

两位小数

让程序显示 价格:3.50。

要显示
价格:3.50
exercise1.c
1#include <stdio.h>2 3int main(void) {4    double price = 3.5;5    printf("价格:%f\n", price);6    return 0;7}
输出
点「运行」或按 Ctrl+Enter
练习 2

对齐

让三个分数都占 5 个字符、靠右对齐,显示成下面这样。

要显示
   95
    8
  100
exercise2.c
1#include <stdio.h>2 3int main(void) {4    int a = 95;5    int b = 8;6    int c = 100;7    printf("%d\n", a);8    printf("%d\n", b);9    printf("%d\n", c);10    return 0;11}
输出
点「运行」或按 Ctrl+Enter
练习 3

折扣

用一个 printf 和这两个变量,显示 折扣 10%,实付 45.50。

要显示
折扣 10%,实付 45.50
exercise3.c
1#include <stdio.h>2 3int main(void) {4    int discount = 10;5    double total = 45.5;6 7    return 0;8}
输出
点「运行」或按 Ctrl+Enter

这一课学会了

  • %.2f 显示两位小数,会四舍五入;变量里的值不变。
  • %5d 至少占 5 个字符、靠右;%-5d 靠左;%8.2f 宽度和小数位一起用。
  • 要显示 %,写 %%。
  • scanf("%d", &x) 读一个整数放进 x;变量前面要写 &,为什么第 15 课再讲。
  • 一个 scanf 可以读好几个值;读 double 用 %lf。
  • scanf 返回成功读到的值的个数。