NOI C++ 课程体系 / 语法入门 / 第7讲
CSP-J 入门级 · 语法入门 · 基本运算专题

C++ 基本运算 完全指南

让程序变身"运算高手" —— 算术、关系、逻辑、自增自减、三目、位运算六大类运算逐一讲透,整数除法、短路求值、++/-- 的先后顺序、0 和 1 的位操作一次看清。

6 大教学模块 6 大类运算精讲 6 个精讲案例 5 大易错点 1 张速查表 15 道分层练习
本讲 · 第 11/56 讲基本运算
模块 01

情景导航

先用"便利店收银机"的故事建立直觉,再用生活类比看清六大类运算的分工,最后给出运算的准确定义和一句好记的口诀。

故事故事引入 —— 便利店的收银机

小强帮姑姑看了一下午便利店,发现收银机其实是一位深藏不露的"运算大师",从开门到打烊,它一秒钟都没停过:

客人买了 3 瓶饮料,每瓶 5 元 → 收银机立刻算出 3 × 5 = 15 元(乘法);

客人递来 20 元 → 收银机算出 20 − 15 = 5 元找零(减法);

遇上"满 100 减 20"的活动 → 收银机先比较"金额 ≥ 100 吗"(关系运算),成立才动手减钱;

"会员并且满 50 元才能抽奖" → 收银机要确认两个条件是否同时满足(逻辑运算);

每卖出一瓶饮料,后台的库存数量自动减 1(自减运算)。

"加、减、乘、除、比一比、判一判 —— 收银机忙活一整天,干的全是运算这件事!"

老师笑着揭秘:程序也一样——算总分、比大小、判断条件、统计个数……每一步都离不开运算。这一讲,我们就把 C++ 里的六大类运算一次认全。

💡 这个故事告诉我们什么?

收银机的每一次动作,都藏着运算的三个要素:

一要有"运算对象"(价格、付款、库存这些参与运算的数);二要有"运算符"(×、−、≥、&& 这些规定怎么算的符号);三要产生"结果"(每次运算都得到一个新值,供下一步使用)。

特别注意的是:比较和判断类运算的结果很特别——不是数,而是"成立或不成立"(true / false)。C++ 把运算分成六大类,下面我们就逐一认识它们。

类比生活类比 —— 身边的四位"运算大师"

把六大类运算和身边的场景对一对号,它们的分工一下子就清晰了:

🧮

收银机 · 算术运算

加、减、乘、除、取余数,算"多少"全靠它,结果永远是一个数。

对应:+ - * / %
⚖

天平 · 关系运算

比轻重、比高矮、看相等不相等,结果是"是或不是"两种答案。

对应:> >= < <= == !=
🎟

游乐券 · 逻辑运算

"门票且学生证"都要带才放行;"雨衣或雨伞"带一样就行。

对应:&& || !
📺

电视遥控 · 自增自减与位运算

音量 +1、−1 一键搞定;遥控器里跑的信号,全是 0 和 1 的世界。

对应:++ -- ? : & | ~ ^ << >>
定义什么是运算

到目前为止,我们写的每一行代码几乎都要和"运算"打交道。把 运算对象(参加运算的数或变量)用 运算符(规定运算规则的符号)连接起来,就构成了 表达式。例如 3 + 5 * 2、a > b、x > 0 && x < 10 都是表达式。表达式求值后会得到一个结果,可以继续参加下一次运算。

类别运算符运算结果典型用途
算术运算+ - * / %数值算数量、算金额、拆数位
关系运算> >= < <= == !=true / false比大小、查相等
逻辑运算&& || !true / false把多个条件组合成一个
自增自减++ --数值变量快速加 1、减 1
三目运算? :取决于条件简单的二选一
位运算& | ~ ^ << >>数值直接操作二进制位

一个表达式里常常同时出现多种运算符,谁先算谁后算?运算符有自己的"级别"——优先级:级别高的先算,同级的一般从左到右,括号永远最优先。本课最后会给出完整优先级表。

基本运算口诀 算术加减乘除余,关系比较真假出;
逻辑与或非相连,全真才真一假无;
自增自减看前后,先用后加要记住;
三目问号挑两边,位运算里零一舞。

口诀里藏着本课的六大主角:算术、关系、逻辑、自增自减、三目、位运算。接下来我们就把它们一个一个请出来,看清各自的写法和规则。

模块 02

知识探究

六大知识点逐个解剖:先看清每类运算符的写法规则,再排好优先级的座次,最后用一段逐步执行动画把规则全部串起来。

①知识点①:算术运算 —— + - * / %

加减乘除与数学写法几乎一样,只是乘号要写 *,除号要写 /;再多加一位新成员 %(取余,算除法剩下的余数)。其中 * / % 的优先级高于 + -,同级运算从左到右。

运算符含义例子结果
+加3 + 58
-减3 - 5-2
*乘3 * 515
/除7 / 23(两个整数相除,截断小数)
/除7.0 / 23.5(有小数参与,保留小数)
%取余7 % 21(除法剩下的余数)
C++除法与取余小实验
#include <iostream>
using namespace std;
int main(){
    cout << 7 / 2 << endl;      // 整数除法:3
    cout << 7.0 / 2 << endl;    // 有小数参与:3.5
    cout << 7 % 2 << endl;      // 取余:1
    return 0;
}
运行结果
3
3.5
1
整数除法"截断"
  • 5 / 2 = 2,不是 2.5,更不是四舍五入的 3;
  • 两个 int 相除,结果还是 int,小数部分直接丢掉;
  • 想保留小数:写成 5.0 / 2 或 1.0 * 5 / 2。
取余三条规则
  • % 两边必须都是整数,7 % 2.5 是错的;
  • 余数符号跟着被除数走:-7 % 2 = -1;
  • a % b == 0 说明 a 能被 b 整除——判断奇偶、判断整除的利器。
②知识点②:关系运算 —— 六位比较大师

关系运算专门负责"比较":大于、小于、等于、不等于……比较的结果只有两种——true(真,打印成 1)或 false(假,打印成 0)。

运算符含义例子结果
>大于5 > 31(真)
>=大于等于5 >= 51(真)
<小于3 < 20(假)
<=小于等于3 <= 20(假)
==等于5 == 51(真)
!=不等于5 != 50(假)
结果就是 1 和 0
  • cout << (5 > 3) << (5 == 4); 输出 10;
  • true 打印成 1,false 打印成 0;
  • bool 类型的变量就是专门存这两个值的。
字符也能比大小
  • 'a' < 'b' 为真——字符比的是 ASCII 码;
  • 三个常用锚点:'A'=65,'a'=97,'0'=48;
  • 所以 'A' < 'a' 的结果也是真。
口诀:== 是比较,= 是赋值;范围判断别连写,拆开 && 才踏实。
③知识点③:逻辑运算 —— && || !

逻辑运算负责把多个条件"组装"成一个大条件:&& 表示"并且",|| 表示"或者",! 表示"取反"。结果同样只有 true / false。

条件 a条件 ba && b(并且)a || b(或者)
真真真真
真假假真
假真假真
假假假假

! 是"唱反调":!true = false,!false = true。优先级:! 高于 &&,&& 高于 ||。记忆口诀:&& 全真才真,|| 一真即真,! 非黑即白。

短路现象
  • && 左边为假时,右边根本不再计算;
  • || 左边为真时,右边直接跳过;
  • 像安检:第一关没过,后面的检查直接免了。
常用搭配
  • x > 0 && x < 10 → "x 在 0 到 10 之间";
  • a % 3 == 0 || a % 5 == 0 → "a 是 3 或 5 的倍数";
  • !(n % 2 == 0) → "n 不是偶数"。
④知识点④:自增与自减 —— ++ 和 --

++ 让变量加 1,-- 让变量减 1,是 a = a + 1 的超短写法。关键区别在于:符号写在变量前面还是后面,决定了"先加还是先用"。

写法含义口诀示例(a = 5)
a++先用后加"先干活,再长个"cout << a++ 输出 5,之后 a 变 6
++a先加后用"先长个,再干活"cout << ++a 输出 6
a--先用后减"先干活,再缩个"cout << a-- 输出 5,之后 a 变 4
--a先减后用"先缩个,再干活"cout << --a 输出 4
a++ 过程拆解
  • int a = 5; cout << a++;
  • 第一步:先把 5 送进 cout 输出;
  • 第二步:a 自己加 1,变成 6。
++a 过程拆解
  • int a = 5; cout << ++a;
  • 第一步:a 先加 1,变成 6;
  • 第二步:再把 6 送进 cout 输出。
口诀:一条语句里只用一次 ++ / --,别写 a+++ 这种"谜语";循环里 i++ 会经常露面(第 5 讲见)。
⑤知识点⑤:三目运算 —— 唯一需要三只眼睛的运算符
条件 ? 表达式1 : 表达式2
条件:判断真或假 ? 和 : 分隔三部分 表达式1:条件为真时取值 表达式2:条件为假时取值

? : 是 C++ 中唯一需要三个操作数的运算符:条件为真,整个表达式取"表达式1"的值;条件为假,取"表达式2"的值。它其实就是 if-else 的一行简写。

C++三目运算小例子
#include <iostream>
using namespace std;
int main(){
    int a = 7, b = 12;
    int big = (a > b) ? a : b;                  // 取较大值
    cout << big << endl;
    cout << ((a % 2 == 0) ? "偶数" : "奇数") << endl;
    return 0;
}
运行结果
12
奇数

对比:m = (a > b) ? a : b; 等价于 if (a > b) m = a; else m = b; 注意:三目嵌套可读性很差,分支一多就老老实实用 if。

⑥知识点⑥:位运算 —— 直接指挥 0 和 1(进阶)

计算机里的所有数据都用二进制保存。位运算不关心"这个数有多大",而是直接对每一个二进制位动手——这是 C++ 特有的"底层功夫",也是竞赛高手的常用技巧。

十进制二进制(按 8 位写)
1200001100
1000001010
运算符名称规则例子结果
&按位与两位都为 1 才是 112 & 108(00001000)
|按位或有一位是 1 就是 112 | 1014(00001110)
^按位异或相同为 0,不同为 112 ^ 106(00000110)
~按位取反0 变 1,1 变 0~12-13
<<左移整体左移,右边补 012 << 248(相当于乘 4)
>>右移整体右移,低位丢弃12 >> 16(相当于除以 2 取整)
奇偶判断神器:n & 1
  • 任何整数 & 1,结果就是它的最低位;
  • 偶数得 0,奇数得 1;
  • if (n & 1) 就等于"如果 n 是奇数"。
移位快速乘除
  • 1 << k 就是 2 的 k 次方:1 << 3 = 8;
  • n << 1 相当于 n 乘 2;
  • n >> 1 相当于 n 除以 2(取整)。
口诀:& | ^ 操作的是二进制位(位运算),&& || 操作的是真假(逻辑运算)——长得像,但完全是两回事,千万别混!
级别运算符优先级 —— 谁先算谁后算

一个表达式里多种运算符同时出现时,按优先级从高到低计算;同级一般从左到右(赋值类从右到左)。记不住没关系——拿不准就加括号。

优先级运算符名称
1(最高)( )括号最优先
2! ++ --逻辑非、自增自减
3* / %乘、除、取余
4+ -加、减
5<< >>移位
6> >= < <=关系比较
7== !=等于、不等于
8&按位与
9^按位异或
10|按位或
11&&逻辑与
12||逻辑或
13? :三目运算
14(最低)= += -= *= /= %=赋值
口诀:括号老大排第一,单目算术移位齐;关系相等按位逻,三目赋值垫底坐。
动画逐步执行演示 —— 一句话串起算术、关系、逻辑

盯着下面这段代码,看计算机如何按优先级一步步算出结果:

C++待演示的程序
#include <iostream>
using namespace std;
int main(){
    int a = 7, b = 2;
    bool flag = (a % b == 1) && (a > b);
    cout << flag;
    return 0;
}
1
a = 7,b = 2 —— 运算对象各就各位
2
a % b → 7 % 2 = 1 —— 先算括号里的取余
3
1 == 1 → 真(1) —— 关系运算出真假
4
a > b → 7 > 2 → 真(1) —— 第二个括号也是真
5
真 && 真 → 真(1) —— 逻辑与:全真才真
6
flag = 1,输出 1 —— 结果存进 bool 变量
运行结果
1
案例6 个由浅入深的案例

案例 1:算术运算实战 —— 文具店小票

题目:笔记本每本 7 元,买 3 本,付了 50 元。输出应付金额、找零,以及总价的一半(体会整数除法)。

C++文具店小票
#include <iostream>
using namespace std;
int main(){
    int price = 7, num = 3, pay = 50;
    int total = price * num;        // 乘法算总价
    int change = pay - total;       // 减法算找零
    cout << "应付:" << total << "元" << endl;
    cout << "找零:" << change << "元" << endl;
    cout << "总价的一半:" << total / 2 << endl;   // 整数除法
    return 0;
}
运行结果
应付:21元
找零:29元
总价的一半:10

解读:21 / 2 = 10 而不是 10.5——整数除法直接截断小数。算钱时如果涉及小数,就要请出小数类型(第 2 讲学过的 double / float)。

案例 2:关系运算 —— 比身高、比成绩、比字符

题目:把几个比较的结果直接打印出来,看看 true / false 长什么样。

C++比较的结果
#include <iostream>
using namespace std;
int main(){
    int height = 138, score = 92;
    cout << (height >= 140) << endl;   // 够不够 1米4
    cout << (score >= 90) << endl;     // 是不是优秀
    cout << (height == 138) << endl;   // 判断相等
    cout << ('A' < 'a') << endl;       // 字符比的是 ASCII
    return 0;
}
运行结果
0
1
1
1

解读:138 >= 140 不成立,输出 0;其余三个成立,输出 1。'A'=65 小于 'a'=97,所以最后一个也是 1。关系运算的结果非 1 即 0,正好可以存进 bool 变量。

案例 3:逻辑运算 —— 奖学金评定

题目:评奖学金的规则:总分 ≥ 270 并且 体育 ≥ 80 才能入选;"全勤 或者 总分 ≥ 300"可以申请特别奖。

C++奖学金评定
#include <iostream>
using namespace std;
int main(){
    int total = 276, sport = 85, attend = 0;
    bool ok = (total >= 270) && (sport >= 80);
    cout << ok << endl;                       // 普通奖学金
    bool sp = (attend == 1) || (total >= 300);
    cout << sp << endl;                       // 特别奖
    cout << !ok << endl;                      // 取反:不能入选?
    return 0;
}
运行结果
1
0
0

解读:276 ≥ 270 与 85 ≥ 80 都成立,&& 得真(1);特别奖两个条件都不满足,|| 得假(0);!ok 把结论翻转,表示"不能入选"为假。

案例 4:自增自减 —— a++ 与 ++a 对比观察

题目:两个变量都从 5 出发,一个用 a++,一个用 ++a,对比输出。

C++a++ 与 ++a
#include <iostream>
using namespace std;
int main(){
    int a = 5, b = 5;
    cout << a++ << endl;   // 先用后加:输出 5
    cout << a << endl;     // 现在 a 是 6
    cout << ++b << endl;   // 先加后用:输出 6
    cout << b << endl;     // b 也是 6
    return 0;
}
运行结果
5
6
6
6

解读:单独一行使用时,a++ 和 ++a 的最终效果一样(变量都加了 1);只有出现在输出、赋值等表达式里时,"先取值还是先加 1"才显出区别。做这类题的秘诀:在草稿上把每一步的变量值标出来。

案例 5:三目运算 —— 求较大值与奇偶输出

题目:读入两个整数,用三目运算符输出较大值,再判断第一个数的奇偶。

C++三目运算实战
#include <iostream>
using namespace std;
int main(){
    int x, y;
    cin >> x >> y;
    int big = (x > y) ? x : y;                     // 较大值
    cout << "较大值:" << big << endl;
    cout << ((x % 2 == 0) ? "x是偶数" : "x是奇数") << endl;
    return 0;
}
运行结果(输入 9 4)
输入 9 4 →
较大值:9
x是奇数

解读:? : 就是 if-else 的简写——条件成立取冒号左边的值,不成立取右边的值。以后遇到"二选一"的小任务,先想想能不能用三目一行解决。

案例 6:现场捉虫 —— 运算里的三个经典错误

题目:下面这段代码藏着 3 处错误,把它们全部找出来。

C++待捉虫的程序
int a = 7, b = 2;
if (a = b) cout << "相等";                // 第 1 处
if (1 <= a <= 10) cout << "在范围内";      // 第 2 处
cout << a % 2.5;                          // 第 3 处
第 1 处
a = b 是赋值:把 b 存进 a,再拿结果 2 当条件(非 0 恒真)。判断相等必须写 a == b。
第 2 处
范围不能连写:先算 1 <= a 得 0/1,再和 10 比,恒为真。应写成 a >= 1 && a <= 10。
第 3 处
% 的两边必须都是整数,a % 2.5 直接编译报错。取余是整数专属运算。

点评:这三处错误分别对应"= 与 == 混淆""范围连写""取余对象不符"——它们会在本课的易错点部分再次出现,先混个脸熟。

模块 03

实践应用

三道动手题:读代码写结果、给代码捉虫子、看要求写程序。先自己做,再点开答案对照。

实践 1 写输出

题目:自增连环问 —— 下面程序输出什么?

C++待跟踪的程序
#include <iostream>
using namespace std;
int main(){
    int a = 10;
    cout << a++ << " ";
    cout << ++a << endl;
    return 0;
}
提示:第一个输出的是"加之前的 a",第二个输出的是"加之后的 a",两步之间 a 的值已经悄悄变了。
点击查看参考答案
答案:10 12
过程:a = 10;a++ 先把 10 输出,a 变 11;++a 先让 a 变 12,再输出 12。
点评:遇到 ++/-- 的题,先把"先用后加 / 先加后用"翻译成两个动作,再一步一步写下每一步的变量值,就不会乱。
实践 2 捉虫挑战

题目:下面这段代码藏着 3 处错误,把它们全部找出来

C++待捉虫的程序
int x = 5;
if (x = 5) cout << "x是5";                // 第 1 行
if (0 < x < 10) cout << "在范围内";        // 第 2 行
bool ok = (x > 3) & (x < 10);             // 第 3 行
点击查看参考答案
第 1 行:x = 5 是赋值——把 5 存进 x,条件变成 5,非 0 恒真,判断完全失效。应写 x == 5。
第 2 行:0 < x < 10 连写不成立:先算 0 < x 得 1,再算 1 < 10 恒为真,等于没判断。应写 x > 0 && x < 10。
第 3 行:& 是按位与(位运算),管的是二进制位;组合真假条件要用逻辑与 &&,写成 (x > 3) && (x < 10)。
实践 3 编程题

题目:数位拆分 —— 读入一个三位数,输出它各位数字之和

例如输入 365,输出 3 + 6 + 5 的和,即 14。

提示:整数除法"砍高位"、取余"留低位":百位 = n / 100,十位 = n / 10 % 10,个位 = n % 10。
点击查看参考答案
C++参考代码
#include <iostream>
using namespace std;
int main(){
    int n;
    cin >> n;
    int a = n / 100;        // 百位
    int b = n / 10 % 10;    // 十位
    int c = n % 10;         // 个位
    cout << a + b + c << endl;
    return 0;
}
示例:输入 365 → 14;输入 909 → 18。
点评:"除砍高位,余留低位"是算术运算最经典的用法之一,以后拆四位、五位数也是同一招,循环学完后还能写成通用版本。
模块 04

总结提升

把六大类运算浓缩成一张表、一句口诀,再用"判断奇偶的一题三解"检验你是否真正掌握了运算的精髓。

总结核心要点总结
类别运算符结果一句话记忆
算术运算+ - * / %数值整数除法截断,余数符号跟被除数
关系运算> >= < <= == !=bool结果非 1 即 0,== 才是比较
逻辑运算&& || !bool与全真才真,或一真即真,非取反
自增自减++ --数值a++ 先用后加,++a 先加后用
三目运算? :看条件if-else 的一行简写
位运算& | ~ ^ << >>数值对二进制位动手,&1 判奇偶
基本运算口诀(再背一遍) 算术加减乘除余,关系比较真假出;
逻辑与或非相连,全真才真一假无;
自增自减看前后,先用后加要记住;
三目问号挑两边,位运算里零一舞。
拓展拓展案例 —— 判断奇偶的一题三解

同样是"判断 n 的奇偶并输出",本课学过的运算能给出三种漂亮的解法:

C++一题三解:判断奇偶
#include <iostream>
using namespace std;
int main(){
    int n = 9;
    // 解法一:取余 + if-else
    if (n % 2 == 0) { cout << "偶数" << endl; }
    else { cout << "奇数" << endl; }
    // 解法二:三目运算
    cout << (n % 2 == 0 ? "偶数" : "奇数") << endl;
    // 解法三:位运算 & 1
    if (n & 1) { cout << "奇数" << endl; }
    else { cout << "偶数" << endl; }
    return 0;
}
运行结果
奇数
奇数
奇数

解读:三种写法殊途同归。解法一最直观;解法二最短;解法三最快——直接看二进制最低位,高手代码里常见。选哪种看场合,但三种都要看得懂、写得对。

🧠 思考与启发

收银机的每一次"嘀",都是运算在幕后工作;程序世界的一切复杂功能,拆到最后都是这些最基本的运算。

想一想:为什么计算机要用二进制保存数据,而不是十进制?为什么整数除法选择"直接截断",而不是四舍五入?提示:截断只需丢掉小数部分,四舍五入还得多看一位——计算机喜欢最省事的规则。再想一想:只用 & | ^ 这些位运算,能不能算出 3 + 5?(这就是计算机加法器的真正原理,有兴趣可以去查查"半加器",会打开一扇新大门。)

模块 05

学习检测

5 个最容易丢分的运算陷阱、一张考前必背速查表,以及可以贴在文具盒上的知识点速记卡。

易错 1

条件里把赋值 = 当成比较 ==

if (x = 5) 不是"判断 x 是否为 5",而是"把 5 存进 x,再拿 5 当条件"——非 0 即真,条件永远成立。

错误写法
if (x = 5) {   // 恒为真
正确写法
if (x == 5) {  // 判断相等
口诀:单等赋值,双等比较;条件里面写双等,少写一个等号全盘错。
易错 2

整数除法当成小数除法

cout << 5 / 2; 输出的是 2,不是 2.5——两个整数相除,小数部分被直接截断,而且不是四舍五入。

想要 2.5 的写法
cout << 5 / 2;      // 输出 2
让一边变成小数
cout << 5.0 / 2;    // 输出 2.5
口诀:两个整数相除,小数直接丢;想留小数,先让一边变小数。
易错 3

范围条件连写:0 < x < 10

数学里的连写 C++ 不认:0 < x < 10 会先算 0 < x 得到 0 或 1,再拿结果跟 10 比,恒为真。范围必须拆成两半用 && 连接。

错误写法
if (0 < x < 10) {   // 恒为真,判断失效
正确写法
if (x > 0 && x < 10) {   // 两个条件同时满足
口诀:范围判断拆两半,中间 && 来牵线。
易错 4

搞混 a++ 与 ++a 的时机

想让屏幕显示"加 1 之后的值",却写成了 a++——先用后加,输出的还是旧值。

错误写法
int a = 5;
cout << a++;    // 输出 5,不是想要的 6
正确写法
int a = 5;
cout << ++a;    // 先加后输出,得到 6
口诀:想先加再显示用 ++a;写完先在草稿上标出每一步的变量值。
易错 5

逻辑运算 && 与位运算 & 混淆

& 是按位与,管的是二进制位;&& 是逻辑与,管的是真假。组合判断条件必须用双符号,单个符号是另一套规则。

按位与(位运算)
bool ok = (x > 3) & (x < 10);
逻辑与(判断条件)
bool ok = (x > 3) && (x < 10);
口诀:判断真假用 && ||,单个符号管零一;长短分明别混用,竞赛场上少丢分。
速查考前速查表 —— 22 个运算符一页带全
运算符含义例子结果
+加3 + 58
-减3 - 5-2
*乘3 * 515
/除(整数)7 / 23(截断)
%取余7 % 21
>大于5 > 31
>=大于等于5 >= 51
<小于3 < 20
<=小于等于3 <= 20
==等于5 == 51
!=不等于5 != 50
&&逻辑与true && false0
||逻辑或false || true1
!逻辑非!true0
++自增a=5 时 ++a6
? :三目3 > 5 ? 1 : 22
&按位与12 & 108
|按位或12 | 1014
^按位异或12 ^ 106
~按位取反~12-13
<<左移12 << 248
>>右移12 >> 16
笔记知识点速记卡
整数除法截断

5 / 2 = 2,不四舍五入;想保留小数,先让一边变成小数。

余数跟被除数

-7 % 2 = -1;a % b == 0 即 a 能被 b 整除。

单等双等分清

= 是赋值,== 是比较;条件判断永远写双等。

范围拆两半

0 < x < 10 必须写成 x > 0 && x < 10,数学连写在 C++ 里不成立。

短路现象

&& 左边为假右边不算,|| 左边为真右边不看。

++ 看位置

a++ 先用后加,++a 先加后用;草稿标值最保险。

n&1 判奇偶

结果 0 是偶数、1 是奇数;1 << k 就是 2 的 k 次方。

拿不准加括号

括号优先级最高,加括号永远不吃亏,逻辑还更清楚。

课后练习

练习作业

巩固六大类运算的规则与优先级,分层练习,点击展开答案与解析。

总结练习3 道综合题
总结 1写输出

题目:下面程序输出什么?

C++除法与取余综合
#include <iostream>
using namespace std;
int main(){
    cout << 9 / 2 << " ";
    cout << 9 % 2 << " ";
    cout << 9.0 / 2 << endl;
    return 0;
}
点击查看参考答案
答案:4 1 4.5
过程:9 / 2 是整数除法,截断得 4;9 % 2 取余得 1;9.0 / 2 有小数参与,得 4.5。
点评:同一个 9,除 2 却得到三个不同的结果——关键看"参与运算的数是不是整数"。
总结 2求值

题目:求表达式 !(3 > 1) || (5 > 2 && 2 > 4) 的值。

提示:先算括号里的关系运算,再算 !,然后 &&,最后 ||。
点击查看参考答案
答案:0(假)
过程:3 > 1 为真,! 翻转为假;5 > 2 为真、2 > 4 为假,&& 得假;假 || 假 = 假。
点评:混合表达式按"括号 → ! → && → ||"的顺序一层层剥开,每层都写出中间结果。
总结 3编程题

题目:读入两个整数,用三目运算符输出其中的较大值。

点击查看参考答案
C++参考代码
#include <iostream>
using namespace std;
int main(){
    int a, b;
    cin >> a >> b;
    cout << (a > b ? a : b) << endl;
    return 0;
}
示例:输入 8 15 → 15。说明:条件 a > b 成立取 a,否则取 b——三目运算就是为"二选一"而生的。
A 组基础巩固(4 题)
A1写输出

题目:下面程序输出什么?

C++整数除法与取余
#include <iostream>
using namespace std;
int main(){
    int a = 17, b = 5;
    cout << a / b << " " << a % b << endl;
    return 0;
}
点击查看参考答案
C++完整参考代码
#include <iostream>
using namespace std;
int main(){
    int a = 17, b = 5;
    cout << a / b << " " << a % b << endl;
    // a / b = 3:整数除法直接截断小数,不四舍五入
    // a % b = 2:余数,17 = 5 × 3 + 2
    return 0;
}
// 实际输出:3 2

答案:3 2

思路:看到两个整数做除法,第一反应就是"这是整数除法,小数部分会被砍掉"。17 ÷ 5 = 3.4,截断得 3;再用"被除数 = 除数 × 商 + 余数"倒推:17 = 5 × 3 + 2,所以余数是 2。

考点:整数除法与取余运算 /、%,对应本讲"算术运算"一节。口诀:除法给商,取余给余,两者是一对好搭档,做数位拆分题必用。

易错:① 把 17 / 5 写成 3.4(那是数学除法,C++ 里两个 int 相除只会得到 int);② 以为取余是"取小数点后的部分",写成 0.4;③ 忘记 % 的操作数必须是整数,写成 17 % 5.0 会编译报错。想得到 3.4,得让一边变成浮点,比如 17 / 5.0。

A2写输出

题目:下面程序输出什么?

C++关系运算连打
#include <iostream>
using namespace std;
int main(){
    cout << (4 > 3) << (4 < 3) << (4 != 4) << endl;
    return 0;
}
点击查看参考答案
C++完整参考代码
#include <iostream>
using namespace std;
int main(){
    cout << (4 > 3) << (4 < 3) << (4 != 4) << endl;
    // 关系运算的结果是 bool,输出时显示为 1(真)或 0(假)
    // 4 > 3  → 1     4 < 3  → 0     4 != 4 → 0
    // 三个数字连着打印,得到 100
    return 0;
}
// 实际输出:100

答案:100

思路:逐个算,每个关系表达式的结果只有两种:真就是 1,假就是 0。4 > 3 成立 → 1;4 < 3 不成立 → 0;4 != 4 不成立 → 0。三个 1/0 直接连在一起输出,就是 100,中间没有任何空格。

考点:关系运算的结果类型与输出形式,对应本讲"关系运算"一节。要点:比较运算返回 bool,用 cout 输出时显示 1 或 0,可以直接当数字用。

易错:① 答案写成 1 0 0(多加了空格)——题目里三个 cout 之间没有空格;② 把 4 != 4 误判为真,以为"!= 就是不等于,4 确实不等于 4"绕晕了,其实 4 等于 4,所以表达式为假即 0;③ 混淆 = 和 ==,写成 4 = 4 不是比较而是赋值,编译会报错。

A3写输出

题目:下面程序输出什么?

C++自增两步走
#include <iostream>
using namespace std;
int main(){
    int x = 6;
    cout << x++ << " " << endl;  // 先输出 6,x 变 7
    cout << ++x << endl;          // 再加 1 变 8,输出 8
    return 0;
}
点击查看参考答案
C++完整参考代码
#include <iostream>
using namespace std;
int main(){
    int x = 6;
    cout << x++ << " " << endl;   // 先用后加:先输出 6,x 再变成 7
    cout << ++x << endl;          // 先加后用:x 先变成 8,再输出 8
    return 0;
}
// 实际输出(第 1 行 6 后面有一个空格):
// 6
// 8

答案:6 8(第一行输出 6 后跟一个空格,第二行输出 8)

思路:盯着 x 的值一步步记。x = 6 时执行 x++:先把当前值 6 交给输出,然后 x 自增成 7。接着执行 ++x:x 先自增成 8,再把这个 8 交给输出。全程 x 悄悄加了两次 1(6 → 7 → 8),但两次输出取到的是不同时刻的值。

考点:前置 ++x 与后置 x++ 的区别,对应本讲"自增自减运算"一节。口诀:后置先用后加,前置先加后用。草稿纸上给变量标出每一步的值是最保险的做法。

易错:① 两行都答成 6 或都答成 8;② 认为 x++ 输出的是自增后的值;③ 忘了两行之间 x 已经变了两次,答成"6 7";④ 在同一个表达式里写 cout << x++ << x++,这种写法求值顺序不确定,不同编译器结果可能不同,考试和比赛里要避免。

A4编程题

题目:温度换算 —— 读入摄氏温度 c(整数),输出华氏温度(公式:c × 9 ÷ 5 + 32)。

提示:先乘后除可以避免精度损失:写成 c * 9 / 5 + 32,不要写成 c * (9 / 5) + 32。
点击查看参考答案
C++参考代码
#include <iostream>
using namespace std;
int main(){
    int c;
    cin >> c;
    cout << c * 9 / 5 + 32 << endl;
    return 0;
}
示例:输入 20 → 68。说明:如果写成 9 / 5 会先得到 1,整个公式就错了——运算顺序和括号的使用直接决定答案对错。

思路:按公式从左往右算 c * 9 / 5 + 32,先乘后除不会丢掉整数部分。

易错:写成 9 / 5 * c,整数除法先把 9/5 算成 1,整个公式的结果就全错了。

B 组提高训练(4 题)
B1编程题

题目:三位数反转 —— 读入一个三位数,把它倒序输出。例如输入 123,输出 321。

提示:个位 = n % 10,十位 = n / 10 % 10,百位 = n / 100,倒过来拼起来。
点击查看参考答案
C++参考代码
#include <iostream>
using namespace std;
int main(){
    int n;
    cin >> n;
    int ge = n % 10;         // 个位
    int shi = n / 10 % 10;   // 十位
    int bai = n / 100;       // 百位
    cout << ge << shi << bai << endl;
    return 0;
}
示例:输入 123 → 321;输入 905 → 509。说明:数位拆分 + 重新拼接,是算术运算的经典组合拳。

思路:用 % 10 取个位、n / 10 % 10 取十位、n / 100 取百位,再按个、十、百的顺序输出。

易错:输出顺序按百、十、个写反;或十位直接写成 n % 10,两次都取到个位。

B2判断简答

题目:下面这段程序会因除以 0 而崩溃吗?为什么?

C++除法遇上短路
#include <iostream>
using namespace std;
int main(){
    int a = 0;
    if (a != 0 && 10 / a > 2) {
        cout << "OK" << endl;
    }
    return 0;
}
点击查看参考答案
答案:不会崩溃。
原因:a != 0 为假,&& 发生短路——右边的 10 / a 根本不会被执行,除以 0 的灾难被逻辑运算顺手拦下了。
点评:短路不只是"省时间",它还经常被用来做保护:把危险的操作放在 && 右边,条件不满足就自动跳过。

思路:利用逻辑与 && 的短路特性——左边 a != 0 为假时,右边的 10 / a 根本不会执行。

易错:以为程序一定会先算右边的 10 / a;把 && 写成 &(按位与)会失去短路保护。

B3编程题

题目:秒数换算 —— 读入秒数 s,输出对应的 时 分 秒。例如输入 3728,输出 1 2 8。

提示:时 = s / 3600;剩下的秒数 = s % 3600,再除以 60 得分;最后 % 60 得秒。
点击查看参考答案
C++参考代码
#include <iostream>
using namespace std;
int main(){
    int s;
    cin >> s;
    int h = s / 3600;          // 时
    int m = s % 3600 / 60;     // 分
    int sec = s % 60;          // 秒
    cout << h << " " << m << " " << sec << endl;
    return 0;
}
示例:输入 3728 → 1 2 8。说明:"除"拿大单位,"余"留小单位,逐级拆分——这种思路在时间、钱币换算题里反复出现。

易错:分钟写成 s / 60 而没有取余,数值会大得离谱;正确写法是 s / 60 % 60 或 s % 3600 / 60。

B4写输出

题目:设 a = 12、b = 10(二进制 00001100 与 00001010),写出下列位运算的结果。

C++位运算四连
#include <iostream>
using namespace std;
int main(){
    int a = 12, b = 10;
    cout << (a & b) << " " << (a | b) << " ";
    cout << (a ^ b) << " " << (a << 1) << endl;
    return 0;
}
点击查看参考答案
C++完整参考代码
#include <iostream>
using namespace std;
int main(){
    int a = 12, b = 10;          // 二进制:00001100  与  00001010
    cout << (a & b) << " ";      // 按位与:00001000 -> 8
    cout << (a | b) << " ";      // 按位或:00001110 -> 14
    cout << (a ^ b) << " ";      // 按位异或:相同为 0、不同为 1 -> 00000110 -> 6
    cout << (a << 1) << endl;    // 左移 1 位 = 乘 2 -> 24
    return 0;
}
// 实际输出:8 14 6 24

答案:8 14 6 24

思路:位运算题的固定动作——先把两个数写成 8 位二进制再一位一位对照。12 = 00001100,10 = 00001010。按位与只有两个 1 才是 1,得 00001000 = 8;按位或有 1 就是 1,得 00001110 = 14;异或"相同为 0、不同为 1",得 00000110 = 6;左移一位把所有位往左推一格、右边补 0,00001100 → 00011000 = 24,正好等于乘 2。

考点:按位与 &、按位或 |、按位异或 ^、左移 << 的运算规则,对应本讲"位运算"一节。两个实用结论:a << k 等于 a × 2ᵏ;n & 1 可以判断奇偶(0 偶 1 奇)。

易错:① 把按位与 & 和逻辑与 && 混用,写成 12 && 10 只会得到 1;② 异或规则记反,算成 00001110;③ 左移误以为"补 1"或是循环移位,其实空出的低位一律补 0;④ 忘记给位运算加括号——cout << a & b 会先算 << 再算 &,结果完全不对,所以务必写成 (a & b)。

C 组挑战提升(4 题)
C1编程题

题目:闰年判断 —— 读入年份,是闰年输出 Yes,否则输出 No。(&& 与 || 综合实战)

提示:闰年规则:能被 4 整除但不能被 100 整除;或者能被 400 整除。
点击查看参考答案
C++参考代码
#include <iostream>
using namespace std;
int main(){
    int y;
    cin >> y;
    if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0) {
        cout << "Yes" << endl;
    } else {
        cout << "No" << endl;
    }
    return 0;
}
示例:输入 2024 → Yes;输入 1900 → No;输入 2000 → Yes。
点评:% 判断整除、&& 组合"并且"、|| 组合"或者"——本题把算术、关系、逻辑三大运算全用上了,是 CSP-J 的高频题。

思路:闰年的条件是「能被 4 整除且不能被 100 整除」或「能被 400 整除」,用 && 和 || 组合表达。

易错:漏掉括号导致逻辑判断错位;只写 y % 4 == 0 会把 1900 这类整百年误判成闰年。

C2编程题

题目:超市促销 —— 读入单价 p、数量 n、是否会员 m(1 是 0 否)。总价满 100 减 20;会员额外再减 5 元。输出应付金额。

提示:先用乘法算总价,再用两个独立判断依次减钱,顺序不能乱(先满减、再会员减)。
点击查看参考答案
C++参考代码
#include <iostream>
using namespace std;
int main(){
    int p, n, m;
    cin >> p >> n >> m;
    int total = p * n;
    if (total >= 100) {
        total = total - 20;     // 满减
    }
    if (m == 1) {
        total = total - 5;      // 会员再减
    }
    cout << total << endl;
    return 0;
}
示例:输入 30 4 1 → 95(120 − 20 − 5)。说明:现实世界的计费规则,就是算术 + 关系 + 逻辑运算的大综合。

思路:先算出总价,再用两个独立的 if 分别处理「满 100 减 20」和「会员减 5」,依次从总价里扣除。

易错:把两个优惠写成 if / else if,会员且满 100 时只减 20,漏掉额外的 5 元。

C3编程题

题目:2 的幂 —— 读入整数 k(0 ≤ k ≤ 20),用位运算输出 2 的 k 次方。

提示:1 的二进制是 00000001,每左移一位就乘一次 2。
点击查看参考答案
C++参考代码
#include <iostream>
using namespace std;
int main(){
    int k;
    cin >> k;
    cout << (1 << k) << endl;
    return 0;
}
示例:输入 10 → 1024。说明:1 << k 就是 k 个 2 相乘。等学到循环和函数,还可以用连乘实现,但位运算一行搞定,又快又帅。

思路:二进制里 1 后面跟 k 个 0 正好等于 2 的 k 次方,也就是 1 << k。

易错:误以为 1 << k 是 1 乘以 2k;k 变大后结果超出 int 范围就会溢出。

C4综合题

题目:三数最大 —— 读入三个整数,用关系与逻辑运算输出其中的最大值。

提示:"a 是最大值"的条件怎么写?a >= b 并且 a >= c,即 a >= b && a >= c。
点击查看参考答案
C++参考代码
#include <iostream>
using namespace std;
int main(){
    int a, b, c;
    cin >> a >> b >> c;
    if (a >= b && a >= c) {
        cout << a << endl;
    } else if (b >= c) {
        cout << b << endl;
    } else {
        cout << c << endl;
    }
    return 0;
}
示例:输入 7 15 9 → 15。
点评:这道题还有"默认值法"解法:先让 maxn = a,再依次用 if (b > maxn)、if (c > maxn) 打擂台——那是第 5 讲循环课"找最大值"的标准套路,提前感受一下。

思路:先用逻辑与判断某个数是否同时不小于另外两数,否则在剩余两数中再比一次。

易错:用 > 而不是 >= 判断,三个数中有相等的情况会漏判,导致一条结果都输出不了。