Kodewick
第 4 课,共 30 课目录

运算符

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

程序最常做的事之一就是算数:一共多少钱、平均几分、还剩多少。C 的加减乘除和数学课上差不多,不过有两个地方常常让人吃惊:7 / 2 等于 3,而 int 也有装不下的时候。

main.c
1#include <stdio.h>2 3int main(void) {4    int price = 12;5    int quantity = 3;6    int total = price * quantity;7    printf("合计:%d 元\n", total);8    return 0;9}
输出
合计:36 元

price * quantity 先算出 36,再放进 total。算式可以放在赋值的右边,也可以直接放进 printf。

算术运算符

运算符意思例子结果
+加17 + 522
-减17 - 512
*乘17 * 585
/除17 / 53
%取余数17 % 52
main.c
1#include <stdio.h>2 3int main(void) {4    int a = 17;5    int b = 5;6    printf("%d + %d = %d\n", a, b, a + b);7    printf("%d - %d = %d\n", a, b, a - b);8    printf("%d * %d = %d\n", a, b, a * b);9    printf("%d / %d = %d\n", a, b, a / b);10    printf("%d %% %d = %d\n", a, b, a % b);11    return 0;12}
输出
17 + 5 = 22
17 - 5 = 12
17 * 5 = 85
17 / 5 = 3
17 % 5 = 2

最后一行的 %% 是第 3 课学的:在 printf 的文字里显示一个 %。

整数除法

两个 int 相除,结果还是 int:小数部分直接丢掉,不四舍五入。所以 17 / 5 是 3,不是 3.4。

main.c
1#include <stdio.h>2 3int main(void) {4    printf("%d\n", 7 / 2);5    printf("%d\n", 19 / 4);6    printf("%d\n", 9 / 10);7    return 0;8}
输出
3
4
0

9 / 10 是 0.9,丢掉小数部分就是 0。另外,不能除以 0:这是未定义行为,我们的引擎会停在那一行。

先猜一猜

这段程序显示什么?

1#include <stdio.h>2 3int main(void) {4    int minutes = 100;5    printf("%d\n", minutes / 60 * 60);6    return 0;7}

取余数

% 算的是整数除法剩下的余数。一个数除以另一个数,商用 /,余数用 %,两个一起用就很方便:

main.c
1#include <stdio.h>2 3int main(void) {4    int eggs = 50;5    int boxes = eggs / 6;6    int left = eggs % 6;7    printf("%d 个鸡蛋:装满 %d 盒,剩 %d 个\n", eggs, boxes, left);8    printf("%d\n", 8 % 2);9    printf("%d\n", 7 % 2);10    return 0;11}
输出
50 个鸡蛋:装满 8 盒,剩 2 个
0
1

一个数 % 2 得 0 就是偶数,不是 0 就是奇数(正数得 1,负的奇数得 -1)。% 只能用在整数上,写 7.5 % 2 会编译错误。

小数除法和类型转换

只要有一边是 double,结果就是 double,小数部分也留着。但是,把整数除法的结果放进 double 已经晚了:

main.c
1#include <stdio.h>2 3int main(void) {4    double a = 7.0 / 2;5    double b = 7 / 2.0;6    double c = 7 / 2;7    printf("%f\n", a);8    printf("%f\n", b);9    printf("%f\n", c);10    return 0;11}
输出
3.500000
3.500000
3.000000

c 是 3.000000:7 / 2 两边都是整数,先算出 3,再放进 double。

如果两个数都是 int 变量,比如求平均分,就在前面写 (double),把它转换成 double 再算:

main.c
1#include <stdio.h>2 3int main(void) {4    int total = 256;5    int count = 3;6    printf("%.2f\n", (double)total / count);7    printf("%.2f\n", (double)(total / count));8    return 0;9}
输出
85.33
85.00

第一行先把 total 变成 256.0,再除,得 85.33。第二行括号里先做了整数除法,得 85,再转换也找不回小数了。反过来,(int)3.9 得 3,小数部分丢掉。

+= 和 ++

「在原来的值上加一点」太常见了,所以有简写:

写法等于
balance += 50;balance = balance + 50;
balance -= 30;balance = balance - 30;
balance *= 2;balance = balance * 2;
visits++;visits = visits + 1;
visits--;visits = visits - 1;
main.c
1#include <stdio.h>2 3int main(void) {4    int balance = 100;5    balance += 50;6    balance -= 30;7    balance *= 2;8    printf("余额:%d\n", balance);9    int visits = 0;10    visits++;11    visits++;12    visits--;13    printf("访问:%d 次\n", visits);14    return 0;15}
输出
余额:240
访问:1 次

点单步,看每一行之后 balance 和 visits 变成多少。++ 和 -- 也可以写在前面(++visits),单独一行时效果一样;放进别的算式里时两种写法有区别,先别那样用。

先乘除,后加减

和数学课一样:先算 *、/、%,再算 +、-;同一级的从左往右。想先算哪部分,就加括号。

main.c
1#include <stdio.h>2 3int main(void) {4    int a = 80;5    int b = 90;6    int c = 70;7    printf("%d\n", 2 + 3 * 4);8    printf("%d\n", (2 + 3) * 4);9    printf("%d\n", a + b + c / 3);10    printf("%d\n", (a + b + c) / 3);11    return 0;12}
输出
14
20
193
80

第三行想求三科的平均分,可是只有 c 被除以 3,得到 193。加了括号的第四行才是 80。

小技巧: 拿不准谁先算的时候就加括号。多一对括号不花什么,读的人也更省心。

整数溢出

第 2 课说过,int 一般占 4 个字节,能放的数有上限,也有下限。<limits.h> 里的 INT_MAX 和 INT_MIN 就是这两个数:

main.c
1#include <stdio.h>2#include <limits.h>3 4int main(void) {5    printf("int 最大:%d\n", INT_MAX);6    printf("int 最小:%d\n", INT_MIN);7    return 0;8}
输出
int 最大:2147483647
int 最小:-2147483648

已经是最大了,再加 1 会怎样?

main.c
1#include <stdio.h>2#include <limits.h>3 4int main(void) {5    int views = INT_MAX;6    printf("%d\n", views);7    views = views + 1;8    printf("%d\n", views);9    return 0;10}
输出
2147483647
signed integer overflow: 2147483647 + 1 cannot be represented in type 'int'

发生了什么: 停在第 7 行:2147483647 + 1 超出了 int 的范围(结果放不下)。

超出 int 的范围叫溢出,这也是未定义行为。在普通的电脑上,它常常悄悄变成一个很大的负数,程序照样往下跑,错误很难发现。我们的引擎会停在溢出的那一行。数可能很大时(比如全世界的人口),就要换一个更大的类型,比如 long long,以后会见到。

练一练

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

练习 1

几小时几分钟

把 total_minutes 换算成小时和分钟,显示 2 小时 15 分钟。

要显示
2 小时 15 分钟
exercise1.c
1#include <stdio.h>2 3int main(void) {4    int total_minutes = 135;5    int hours = 0;6    int minutes = 0;7    printf("%d 小时 %d 分钟\n", hours, minutes);8    return 0;9}
输出
点「运行」或按 Ctrl+Enter
练习 2

摄氏转华氏

华氏温度 = 摄氏温度 × 9 ÷ 5 + 32。算出 fahrenheit,显示 36.6°C = 97.9°F。

要显示
36.6°C = 97.9°F
exercise2.c
1#include <stdio.h>2 3int main(void) {4    double celsius = 36.6;5    double fahrenheit = 0;6    printf("%.1f°C = %.1f°F\n", celsius, fahrenheit);7    return 0;8}
输出
点「运行」或按 Ctrl+Enter
练习 3

修好它

60 道题答对了 45 道,正确率应该是 75.0%,这段程序却显示 0.0%。改好它,让它显示 正确率:75.0%。

要显示
正确率:75.0%
exercise3.c
1#include <stdio.h>2 3int main(void) {4    int correct = 45;5    int total = 60;6    double rate = correct / total * 100;7    printf("正确率:%.1f%%\n", rate);8    return 0;9}
输出
点「运行」或按 Ctrl+Enter

这一课学会了

  • + - * / % 是加、减、乘、除、取余数。
  • 两个 int 相除,小数部分直接丢掉:7 / 2 是 3;% 给出余数。
  • 有一边是 double,结果就是 double;两个 int 变量相除要小数,写 (double)a / b。
  • +=、-=、*= 是简写;x++ 加 1,x-- 减 1。
  • 先乘除后加减,同一级从左往右;拿不准就加括号。
  • int 有上限 INT_MAX,超出去是溢出,这是未定义行为。