大卫信奥 · J1知识点总结 · 直播课

J1 知识点 · 十二单元合集

从 C++ 的第一行代码,到分支、循环、数组与综合练习。
一个学期,十二段旅程——

← 返回主页
J1 封面插图
课程目录
大卫信奥 · J1 知识点 · 一单元
01

C++ 从这里开始

认识 Dev-C++ 与 OJ,写出第一个程序,学会变量、输入与输出。

环境与工具 基本语法 输入输出 习题讲解
C++ 从这里开始封面
今日路线

四个环节,从工具走到第一个完整程序

01
环境篇
打开 Dev-C++,看懂错误提示,在 OJ 提交作业。
02
语法篇
四则运算、变量与赋值、变量命名规则。
03
输入输出
用 cin 读数据、用 cout 写结果。
04
习题讲解
综合练习:输出字符菱形。
01
PART 01 · 环境篇

先把工具用好

写代码、看错误、交作业——第一步是熟练使用 Dev-C++ 和 OJ。

Dev-C++ 错误提示 OJ 提交
Dev-C++ 使用

四步,写出并运行你的第一个程序

1
打开 Dev-C++
双击图标进入主界面。
2
新建源代码
文件 → 新建 → 源代码。
3
保存文件
文件 → 保存 / Ctrl+S。
4
编译并运行
编译运行,无错误即成功。
Dev-C++ · 源程序编辑器
文件 编辑 编译 运行
#include <iostream> using namespace std; int main() { cout << "Hello, World!" << endl; return 0; }
Dev-C++ 错误提示

报错不是坏事:红线是定位错误的线索

错误提示是线索,不是失败——先把提示读一遍,再动手改。

Dev-C++ · 编译失败
源代码与诊断示意(行列以实际编译器为准)
#include <iostream> using namespace std; int main() { cout << "Hello"← 少了一个分号 return 0; }
输出窗口
[Error] expected ';' before 'return' 检查 cout 行末尾和紧随的 return 附近
①
看红色行
编译失败时,红线指向的地方及其上一行都要检查,下方输出窗口显示具体错误信息。
②
修改,再编译
找到错误位置修改代码,重新编译运行,直到没有错误提示为止。
OJ 使用

收藏 OJ,找到你的作业

https://oj.davidoi.com.cn/rs/
大卫信奥 Online Judge
登录 → 团队 → J1 团队 → 团队习题集
复制代码 → 粘贴到文本框
点击绿色提交 → 总分 100
1
登录并收藏
打开网址登录,把网站收藏起来。
2
进入 J1 团队
点击“团队”,找到 J1 的团队。
3
打开团队习题集
点击“团队习题集”看作业。
✓
提交后查看测试点详情:总分 100 说明代码正确,否则需要修改再提交。
02
PART 02 · 语法篇

C++ 的地基

运算、变量、命名规则——这些小零件组合起来就是程序。

四则运算 变量与赋值 命名规则
C++ 基本语法

加、减、乘、除——注意整数除法

+
加法
1 + 100
−
减法
100 - 1
*
乘法
2 * 50
/
除法
5 / 2 = 2
/
整数除法会丢掉小数部分。
5 / 2 的结果是 2,不是 2.5。
练一练:cout << 1 + 100 的输出是什么?
A101
B1+100
C1+100=101
D1+100=1
✓ 选 A:101 —— 程序会先算出 1 + 100,再输出结果。
C++ 基本语法

变量是装数据的盒子,赋值是把数据放进去

=
定义:类型 变量名;  赋值:变量名 = 值;
创建变量 → 放进数据
int a; // 创建变量 a = 10; // 变量赋值
aint
10
盒子类型 int
装上 10
blong long
10000000000
整数太大?
换 long long
常见类型
int long long double char string
C++ 基本语法

重新赋值:最后一次赋值生效

可以反复赋值,以最后为准
int a = 10; a = 20; // a 现在是 20 int b = a; // b 拿到 a 的值:20
aint
20
→
重新赋值
旧值 10 被覆盖
bint
20
←
int b = a;
复制 a 的值给 b
!
小技巧:交换 a 和 b 的值
int temp = a; // ① 暂存 a a = b; // ② a 换成 b b = temp; // ③ b 取回值
C++ 基本语法

变量名:四条规则,过一遍再起名

1
组成
字母、数字、下划线
2
开头
不能以数字开头
3
关键字
不能是关键字
4
大小写
a 和 A 是不同变量
练一练:下列变量名哪些是合法的?
A____
B1a
Ca1 / a2
D__b
Ea__1
Fa1_
G11_a
✓ 用户可用:C、F;B、G 数字开头;A、D、E 含双下划线,属于实现保留名。
03
PART 03 · 输入输出篇

程序和你对话

cin 从键盘读数据,cout 把结果写到屏幕。

cin 输入 cout 输出
C++ 输入输出

cin:从键盘读数据

cin 会根据变量的类型自动读入,不需要额外的类型转换。scanf 也能输入,留到后面章节再讲。

读入一个整数
int a; cin >> a; // 把输入存进变量 a
运行窗口
输入:10 ↓ 变量 a = 10
连续读入多种类型
int a; double b; char c; string d; cin >> a >> b >> c >> d;
运行窗口
输入:10 3.14 A Hello ↓ a=10 b=3.14 c='A' d="Hello"
练一练

已知输入 1 2,程序输出什么?

程序
int x = 10, y = 20; cin >> x >> y; // 输入:1 2 cout << x << " " << y;
输入 1 2 (两个数用空格隔开) → 覆盖原值,输出 1 2
程序的输出是什么?
A10 20
B1 2
C2 1
D10 2
✓ 选 B:输入覆盖原值,输出 1 2。
!
cin 会把新输入的数覆盖原来的值——变量里最后放进去的才是它的值。
C++ 输入输出

cout:把数据输出到屏幕

整数、浮点数、字符、字符串都可以直接输出,endl 换行,\n 也可以。printf 留到后面章节再讲。

输出一个变量并换行
int a = 10; cout << a << endl;
输出:10(并换行)
多种类型一起输出
int a = 10; double b = 3.14; char c = 'A'; string d = "Hello!"; cout << a << " " << b << " " << c << " " << d;
输出:10 3.14 A Hello!
04
PART 04 · 习题篇

综合挑战

用今天的全部知识,做一道完整的输出题。

拆解思路 编写代码 运行验证
习题讲解 · 输出字符菱形

写代码前,先数清楚每行有几个空格

*
***
*****
***
*
行空格星号样子
121*
213***
305*****
413***
521*
#
上半部分空格 −1、星号 +2,
下半部分正好对称。
习题讲解 · 输出字符菱形

一行一行 cout,注意开头的空格

#include <bits/stdc++.h> using namespace std; int main() { cout << " *" << endl; cout << " ***" << endl; cout << "*****" << endl; cout << " ***" << endl; cout << " *" << endl; return 0; }
运行结果
*
***
*****
***
*
每行开头的空格也要原样输出
拓展 · 带余除法

除不尽的整数:商和余数

/ 得商,% 得余数
int a = 7, b = 3; cout << a / b << " " << a % b << endl;
输出:2 1  先得商 2,余数 1
% 运算:只取余数
7 % 3 = 1
10 % 2 = 0
17 % 4 = 1
%
判断奇偶很常用:x % 2 == 0 就是偶数。
小结

今天你学会了:

环境篇
打开 Dev-C++ 编译与运行 看懂错误提示 在 OJ 提交作业
语法篇
四则运算 定义变量 变量命名规则
输入输出
cin 输入 cout 输出 输出字符菱形
大卫信奥 · J1 知识点 · 二单元
02

运算符、表达式与数位分离

认识 + - * / % 五个运算符,会写表达式,把整数的每一位拆出来。

运算符 表达式 关键字 数位分离
运算符、表达式与数位分离封面
今日路线

四个环节,从运算符走到完整程序

01
运算符
+ - * / %,特别注意整除与取模。
02
表达式
常量、变量、运算符组成,有优先级。
03
自赋值与关键字
a=a+1 的简写,不能当变量名的词。
04
数位分离
用整除和取模拆出每一位数字。
01
PART 01 · 运算符与表达式

C++ 的算术运算

加减乘除取模,再加上表达式和优先级——先学会算,再学会算得对。

五个运算符 表达式 优先级
C++ 基本语法

加、减、乘、除、取模——五个基本运算符

+
加法
1 + 100
−
减法
100 - 1
*
乘法
2 * 50
/
除法
5 / 2 = 2
%
取模
10 % 3 = 1
/
/ 两边都是整数时,结果仍是整数(整除):5 / 2 得 2,不是 2.5。 % 取模只能用于整数,不能用于浮点数。
C++ 基本语法

表达式 = 常量 + 变量 + 运算符

表达式是一个计算式,值是算出来的结果,可以有常量,也可以有变量。

1 + 3
1 和 3 是常量
(1+2)*3-4/5
多个运算符
a + b * c
a b c 都是变量
a + 1
变量 + 常量
!
优先级:括号最高,乘除 / 取模高于加减。 例:2 + 3 × 4 = 14,(2 + 3) × 4 = 20。
练一练

先别看答案,猜猜屏幕上打出什么

程序
cout << 1 << "+" << 100 << "="; cout << 1 + 100 << endl;
程序的输出是什么?
A101
B1+100
C1+100=101
D1+100=1
✓ 选 C:先输出文字 1+100=,再算出 101,连成 1+100=101。
练一练

输入长方形长和宽,输出周长和面积

输入两个整数(1~20 之间),输出周长和面积,用空格隔开。

程序
int a, b; cin >> a >> b; cout << 2*(a+b) << " " << a*b << endl;
输入:8 5
输出:26 40
!
周长 = 2 × (a + b),面积 = a × b。
验证
2 × (8+5) = 26,8 × 5 = 40
练一练

买文具:50 元能买几本,剩多少?

明明拿 50 元买练习本,一本 3 元,最多能买多少本?还剩多少钱?

程序
cout << 50 / 3 << " " << 50 % 3 << endl;
输出:16 2
/
数量 = 总价 ÷ 单价,剩余 = 取模。
50 / 3
16
→
最多能买
16 本
50 % 3
2
→
还剩
2 元
练一练

算出下面每个表达式的值

/ 得商,% 得余,从左到右逐级计算。

3 / 10
0
3 % 10
3
100 / 8 / 2
6
20 % 5
0
23 % 10
3
47 % 7 % 2
1
%
从左到右算:47 % 7 = 5,再 5 % 2 = 1,100 / 8 = 12,再 12 / 2 = 6。
02
PART 02 · 自赋值与关键字

把值算给自己

a = a + 1 有更短的写法,还有一类单词不能拿来当变量名。

自赋值 += -= *= /= 关键字
C++ 基本语法

自赋值:把变量自己的值算一遍,再放回自己

=
a = a + 1 意思是:把 a 的值加 1,再赋回 a。
写法对照(各行分别说明)
int a = 1; a = a + 1; // 等价于 a += 1 a = a - 1; // 等价于 a -= 1 a = a * 2; // 等价于 a *= 2 a = a / 2; // 等价于 a /= 2
aint
1
→
独立例 1:a=1
a += 1 后
a 变成 2
aint
2
→
独立例 2:a=2
a *= 2 后
a 变成 4
练一练

跟着代码一步步算,a 和 c 最后是多少?

程序
int a = 2, b = 3, c = 8; a -= b; // a = a - b = 2 - 3 = -1 c *= a; // c = c * a = 8 × (-1) = -8
aint
-1
←
a -= b
2 - 3 = -1
cint
-8
←
c *= a
8 × (-1) = -8
✓ 结果:a = -1,c = -8。
C++ 基本语法

关键字:语言里有特殊意义的单词

关键字不能用作变量名、函数名或其它标识符。

int
整数类型
int a = 10;
float
浮点类型
float b = 3.14;
if
条件语句
二选一分支
while
循环语句
条件成立就重复
for
循环语句
数次数循环
…
还有很多
return / break 等
!
全部关键字查这里(延伸):cppreference.com/w/cpp/keyword
03
PART 03 · 数位分离

把一个整数拆开来

用整除和取模,把 12345 的每一位都取出来——这是很多题目的第一步。

除 10^n 取余 % 10 三位数反转
C++ 基本语法 · 数位分离

先除以 10 的幂,再对 10 取余

取某一位:先 / 10^n 把这一位移到个位,再 % 10 取出来。

万位
1
千位
2
百位
3
十位
4
个位
5
取千位(= 2)
12345 / 1000 = 12 12 % 10 = 2
取百位(= 3)
12345 / 100 = 123 123 % 10 = 3
#
规律:第 k 位 = (n / 10^(k-1)) % 10 例:12345 / 1000 = 12,再 % 10 = 2。
练一练

把 461 反转成 164

分别取出个位、十位、百位,再组合起来。

程序
int n; cin >> n; // 输入 461 int g = n % 10; // 个位 1 int s = n / 10 % 10; // 十位 6 int b = n / 100; // 百位 4 cout << g*100 + s*10 + b; // 164
输出:164
个位 g = 461 % 10 = 1
十位 s = 461 / 10 % 10 = 6
百位 b = 461 / 100 = 4
✓ 组合:1×100 + 6×10 + 4 = 164。
04
PART 04 · 习题讲解

用今天学的知识做题

四道题:先读题,再想公式,最后写代码、看运行结果。

A+B (a+b)×c 带余除法
习题讲解 · A+B 问题

给定两个整数,输出它们的和

程序
#include <iostream> using namespace std; int main() { int a, b; cin >> a >> b; cout << a + b << endl; return 0; }
运行窗口
输入:3 5 输出:8
+
cin 读入 a、b,cout 输出它们的和。
习题讲解 · (a+b) × c

先求 a+b,再乘以 c

程序
#include <iostream> using namespace std; int main() { int a, b, c; cin >> a >> b >> c; cout << (a + b) * c << endl; return 0; }
运行窗口
输入:2 3 4 输出:20
( )
括号改变优先级:(2+3)×4 = 20。
习题讲解 · 带余除法

/ 得商,% 得余

程序
#include <iostream> using namespace std; int main() { int a, b; cin >> a >> b; cout << a / b << " " << a % b << endl; return 0; }
运行窗口
输入:7 3 输出:2 1
%
7 / 3 得商 2,7 % 3 得余 1。
! 思考题:等差数列末项怎么算?(按 → 继续)
思考题 · 等差数列末项

末项 = 首项 + 公差 × (项数 − 1)

相邻两项的差是常数,即公差。例:1, 3, 5, 7, 9 公差为 2。

程序
int a, b, d, n; cin >> a >> b >> n; // a1, a2, 项数 d = b - a; cout << a + d * (n - 1) << endl;
输入:1 3 5 输出:9
a
a_n = a_1 + (n − 1) × d
其中 d = b − a 是公差
延伸阅读
等差数列末项 · 题目 447
还有等比数列、斐波那契数列。
小结

今天你学会了:

运算符与表达式
+ - * / % 整除 % 只能整数 优先级:括号 > 乘除% > 加减
自赋值与关键字
a = a + 1 += -= *= /= 关键字不能当变量名
数位分离
先除 10^n,再 % 10 三位数反转 带余除法
大卫信奥 · J1 知识点 · 三单元
03

C++ 的数据类型

整数、浮点、字符、布尔——把数据放进正确的盒子,是写好 C++ 的第一步。

整数类型 浮点数 字符与 ASCII 类型转换
C++ 的数据类型封面
今日路线

四个部分,把数据类型的家底摸清

01
整数篇
有符号、无符号、整型溢出。
02
浮点篇
float、double 与精度误差。
03
字符篇
char、ASCII 码、字符运算。
04
bool 与转换
bool、隐式与显式类型转换。
01
PART 01 · 整数篇

把整数装进正确的盒子

有符号、无符号、溢出——范围的边界决定它能装多大的数。

有符号整型 无符号整型 整型溢出
有符号整型

范围取决于类型宽度与目标平台

类型字节数(示例)可表示范围
signed char1−128 ~ 127
short2−32768 ~ 32767
int4−2147483648 ~ 2147483647
long4(本表示例)与本表 int 相同
long long8−2⁶³ ~ 2⁶³−1
!
上表是一组常见平台示例,采用 8 位字节;C++ 不保证 long 一定是 4 字节。普通 char 是否有符号也由实现决定。用 sizeof(T)、numeric_limits<T>::min()/max() 查看实际环境。
练一练

整型快到边界时,会发生什么?

下面的程序输出什么?(int a = 2147483647)
int a = 2147483647; cout << a << endl; cout << a + 1 << endl;
A2147483647, 2147483648
B2147483647, -2147483648
C2147483647, 0
D有符号溢出,行为未定义
✓ 选 D:假定 int 为 32 位。a+1 超出有符号范围,行为未定义,不能保证回绕。
下面的程序输出什么?(unsigned int a = 0)
unsigned int a = 0; cout << a - 1 << endl;
A-1
B0
C4294967295
D编译错误
✓ 选 C:0 - 1 回绕到最大值 4294967295(2^32-1)。
无符号整型

N 位无符号整数:0 到 2ᴺ−1

类型字节数(示例)可表示范围
unsigned char10 ~ 255
unsigned short20 ~ 65535
unsigned int40 ~ 4294967295
unsigned long4(本表示例)与本表 unsigned int 相同
unsigned long long80 ~ 2⁶⁴−1
!
本表同样采用明确的平台示例。无符号算术按 2ᴺ 取模;把负数转成无符号数后得到的非负值,通常不是题目想要的负数结果。
整数边界 · unsigned

无符号按范围取模;有符号溢出需避免

unsigned char x = 255; // 本例采用 8 位字节 cout << int(x) << endl; x = x + 1; // 转回 unsigned char cout << int(x) << endl;
输出:255 0
unsigned char
255
+1 →
按 256 取模
0

普通 char 的有无符号由实现决定。
想表达有无符号,请显式写类型。

!
signed int 的最大值再加 1 是未定义行为;类型转换的规则与算术溢出要分别分析。
02
PART 02 · 浮点数篇

小数也有自己的盒子

浮点数能表示小数,但表示是有限的——小心精度误差。

float / double 精度问题
浮点数类型

范围、精度、占用空间分别看

类型常见大小最大有限值数量级有效数字
float4 字节约 ±3.4×10³⁸约 6~7 位
double8 字节约 ±1.8×10³⁰⁸约 15~16 位
long double随实现变化至少覆盖 double 的值域至少不低于 double
!
浮点数可表示 0 和负数。常见表里的 1.2e−38、2.2e−308 是最小正正规数的数量级;更接近 0 的非正规数精度会降低。日常先选 double,需要更高精度时再核对 long double 的实际实现。
练一练

float 算出来的小数,真的精确吗?

程序
float a = 1.0, b = 3.0; cout << a / b << endl;
程序的输出是什么?
A0.333333
B0.333333343
C0.33
D0.3
✓ 选 A:cout 默认保留 6 位有效数字,输出 0.333333;存储近似值与显示精度要分开。
!
这就是为什么日常建议用 double:它精度更高,误差更小。
浮点数精度问题

别用 == 直接比较小数

直接相等 · 出错
double a = 0.1, b = 0.2, c = 0.3; if (a + b == c) cout << "true"; else cout << "false";
输出:false (不相等)
?
0.1、0.2、0.3 无法精确表示,二进制是无限循环。
用误差范围 · 正确
double a = 0.1, b = 0.2, c = 0.3; if (abs(a + b - c) < 1e-9) cout << "true"; else cout << "false";
输出:true (误差极小)
✓
用很小的误差范围 abs(a-b) < 1e-9 判断相等。
!
比较浮点数时,应避免直接用 ==,改用很小的误差范围判断是否相等。
03
PART 03 · 字符篇

字符背后,其实是数字

char 存字符也存整数——ASCII 码是中间那座桥。

字符类型 ASCII 码 字符运算
字符类型

char:字符、整数、转义字符都可以

char 只占 1 字节,本质是一个整数,可以拿来存字符、整数或转义字符。

三种存法
char a = 'a'; // 字符 char b = 66; // 整数 → 字符 'B' char c = '\n'; // 转义字符:换行
存整数 66,读出来就是字符 'B'。
#
常用的转义字符:\n 换行、\t 制表、\r 回车。
\0
\0 是特殊字符(ASCII 值 0),表示字符串结束,
例如 "hello" 在内存里是 {'h','e','l','l','o','\0'}。
ASCII 码

字符 ↔ 数字:ASCII 对照表

'A'⇄65
'a'⇄97
'0'⇄48
' '⇄32
大写字母 A - Z
65 ~ 90
小写字母 a - z
97 ~ 122
数字 0 - 9
48 ~ 57
常用特殊字符
空格 32 · \n 10 · \r 13 · \t 9
练一练:下面的 ASCII 码对应什么字符?
65 97 48 32
AA a 0 空格
Ba A 0 空格
CA a 空格 0
D0 a A 空格
✓ 选 A:65→A,97→a,48→0,32→空格。
int 与 char 的关系

字符和整数:一个盒子可以互相转换

char ↔ int 互转
cchar
'A'
→
nint
65
int n = c
取 ASCII 值
dchar
'B'
←
66int
66
char d = 66
转成字符
字符运算 · 大小写差 32
cout << (char)('A' + 1); // 'B' cout << ('B' - 'A'); // 1 cout << ('A' < 'a'); // 1 char lo = 'A' + 32; // 'a' char up = 'b' - 32; // 'B'
ASCII 英文字母:小写 = 大写 + 32,大写 = 小写 − 32
练一练:下面程序的输出?
char c = 'A'; int n = c; cout << n << endl; // ? n = 66; c = n; cout << c << endl; // ?
AA B
B65 66
C65 B
DA 66
✓ 选 C:n=65,c='B'。
练一练 · 字符

字符和 ASCII:再算两道

下面程序的输出是什么?
char c1 = 'A', c2 = 65; int n1 = 'B', n2 = c1 + 1; cout << c1 << " " << c2 << " " << n1 << " " << n2 << endl;
AA A B 66
B65 A 66 B
CA A 66 66
DA 65 B 66
✓ 选 C:c1='A',c2=65→'A',n1='B'→66,n2=c1+1→66。
下面程序的输出是什么?
cout << ('z' - 'a') << endl; cout << ('9' - '0') << endl; cout << (char)('a' + 3) << endl;
A25 9 c
B25 9 d
C26 9 d
D26 9 c
✓ 选 B:'z'-'a'=25,'9'-'0'=9,'a'+3='d'。
04
PART 04 · bool 与类型转换

真假,以及类型的转换

bool 只有真和假,类型转换要小心丢失信息。

bool 类型 隐式转换 显式转换
布尔类型

bool:真和假,本质是 1 和 0

true / false 存成 1 / 0
bool a = true, b = false; cout << a << endl; // 1 cout << b << endl; // 0
=
bool 的占用由实现决定(常见为 1 字节),可隐式转换:非 0 值变 true(1),0 变 false(0)。
练一练:下面程序的输出?
bool a = 5, b = -3, c = 0; cout << a << " " << b << " " << c << endl;
A5 -3 0
B1 1 0
Ctrue true false
D5 -3 false
✓ 选 B:5 和 -3 都转成 true(1),0 转成 false(0)。
类型转换

类型转换:会自动,也可以手动

隐式转换 · 自动
int a = 1; double b = a; // int 自动转 double
b = 1.0 朝精度更高的方向自动转
显式转换 · 手动
double a = 1.23; int b = (int)a; // C 风格 int c = static_cast<int>(a); // 更安全
b = 1,c = 1 小数部分被截掉
!
转换风险:精度丢失、数据溢出、符号丢失、未定义行为。
练一练:a=3, b=2,输出是什么?
cout << a / b << endl; cout << (double)a / b << endl;
A1 1.5
B1.5 1.5
C1 1
D编译错误
✓ 选 A:1 和 1.5。
习题讲解

两道题:一个防溢出,一个取 ASCII 值

A × B · 用 long long 防溢出
#include <iostream> using namespace std; int main() { long long a, b; cin >> a >> b; cout << a * b << endl; return 0; }
!
数据范围大,用 long long 存结果,防止 int 溢出。
打印 ASCII 码 · int(c)
#include <iostream> using namespace std; int main() { char c; cin >> c; cout << int(c) << endl; return 0; }
!
用 int(c) 输出输入字符的 ASCII 码,用 char 类型存字符。
小结

今天你学会了:

整数篇
有符号整型 无符号整型 整型溢出
浮点与字符
float / double 浮点精度 char 与 ASCII
布尔与转换
bool 1 / 0 隐式转换 显式转换
大卫信奥 · J1 知识点 · 四单元
04

自增自减与格式化输入输出

搞懂 ++ 和 -- 的取值顺序,学会 scanf 与 printf 精确控制输入输出。

自增自减 scanf printf 精度控制
自增自减与格式化输入输出封面
今日路线

三个环节,把 ++/-- 和格式化输出用熟

01
自增与自减
前缀/后缀取值、复合赋值、字符自增、优先级。
02
格式化输入输出
scanf 输入、printf 输出、特殊格式、精度控制。
03
精度与习题
float/double 差异、浮点比较、日期格式化、习题讲解。
01
PART 01 · 自增与自减篇

先搞清楚 ++ 和 -- 怎么取值

前缀先加后取值,后缀先取值后加,复合赋值就是它的简写。

自增自减 复合赋值 字符自增 优先级
C++ 自增与自减

前缀 ++x 先加后取值,后缀 x++ 先取值后加

前缀:++x 先加后取值
int x = 5; cout << ++x << endl; // 输出 6
x
5
→
++x 的值
6
先加 1 再取值,x 也变成 6。
后缀:x++ 先取值后加
int x = 5; cout << x++ << endl; // 输出 5
x
5
→
x++ 的值
5
先取旧值,再加 1,x 变成 6。
练一练

x = 5 时,这三个输出是什么?

程序
int x = 5; cout << ++x << endl; cout << x++ << endl; cout << x << endl;
程序的输出是什么?
A6 6 7
B6 5 6
C6 6 6
D5 6 7
✓ 选 A:6 6 7 —— 第二行 x++ 先取值(6)再加,最后 x 是 7。
自增示例

链式自增:逐行跟踪 x 和 y 的值

程序
int x = 0, y = 0; x = ++y; // y 变 1,x=1 y = ++x; // x 变 2,y=2 x = y++; // x 取 2,y 变 3 y = x++; // y 取 2,x 变 3
语句xy说明
x = ++y11y 先加 1,x 取 1
y = ++x22x 先加 1,y 取 2
x = y++23x 取旧值 2,y 加 1
y = x++32y 取旧值 2,x 加 1
!
把每个表达式当成取值 + 变量变化两步,就不会写错。
C++ 自增与自减

复合赋值:x += 5 就是 x = x + 5

简写,读起来更快
x += 5; // x = x + 5 x -= 5; // x = x - 5 x++; // 等价于 x += 1 x--; // 等价于 x -= 1
+=
加法赋值
x += 5
-=
减法赋值
x -= 5
*=
乘法赋值
x *= 5
!
还有 /= 和 %=
x /= 5; // x = x / 5 x %= 5; // x = x % 5
C++ 自增与自减

字符也能自增:让字符走到下一个

字符按顺序向后走
char c = 'X'; c++; // c 变成 'Y' cout << c << endl; // 输出 Y c += 2; // 'Y' + 2 = '[' cout << c << endl; // 输出 [
运行窗口
Y [
下面的代码输出什么?
char c = 'X'; c++; cout << c << endl; c += 2; cout << c << endl;
AY [
BY Z
CY A
DX Y
✓ 选 A:Y [ —— X 加 1 是 Y,Y 加 2 是 [。
C++ 自增与自减

优先级:++ 比算术高,+= 比算术低

++ 优先级高于算术
x = 5 + ++y; // 先 ++y,再 5 + y
+= 优先级低于算术
x += 5 + y; // 等价于 x = x + (5 + y)
!
优先级决定分组。带副作用的复杂表达式建议拆成独立语句;括号本身不普遍保证执行先后。
练一练:a=5, b=10,c = a++ + ++b,输出 a b c 是?
A6 11 17
B6 11 16
C5 11 16
D6 10 16
✓ 选 B:6 11 16 —— a++ 取 5(a 变 6),++b 得 11,c = 16。
02
PART 02 · 格式化输入输出篇

让程序精确控制输入输出

scanf 读入、printf 输出,格式符号决定数据的宽度和小数位。

scanf 输入 printf 输出 特殊格式 精度控制
C++ 格式化输入输出

scanf:带上 & 的格式化输入

按格式读入
int x, y; scanf("%d %d", &x, &y); cout << x << " " << y << endl;
运行窗口
输入:10 20 输出:10 20
&
读取 int/float/double/char 对象时传地址(如 &x)。%s 传字符数组首地址,不能直接传 std::string。
最常用的 4 个
%d
整数
%f
浮点数
%c
字符
%s
C 字符串
%f → float*;%lf → double*。字符数组:char s[20]; scanf("%19s", s);
C++ 格式化输入输出

printf:不需要 & 的格式化输出

按格式输出
int x = 5, y = 10; printf("x = %d, y = %d\n", x, y);
运行窗口
x = 5, y = 10
x
和 scanf 不同:printf 不需要 &,直接写变量名。
常用格式符号
%d
int 整数
%f
浮点
%c
字符
%s
C 字符串
%lld
long long
%lf
与 %f 相同
%x
十六进制
%o
八进制
float 作为 printf 实参会提升为 double;%f 与 %lf 浮点输出含义相同。
C++ 格式化输入输出

特殊格式:宽度、对齐、补零、小数位

格式数值示例输出(_ 为空格)
%5d42___42
%-5d4242___
%05d4200042
%.2f3.141593.14
%8.2f3.14159____3.14
%
%md 中 m 是总宽度(右对齐),%-md 左对齐,%0md 用 0 补齐,%m.nf 总宽 m、保留 n 位小数。
练一练

输入 123、3.14、A(用空格分隔),输出什么?

程序
int a; float b; char c; scanf("%d %f %c", &a, &b, &c); printf("a=%d, b=%.2f, c=%c\n", a, b, c);
运行窗口
输入:123 3.14 A a=123, b=3.14, c=A
程序的输出是什么?
Aa=123, b=3.14, c=A
Ba=123, b=3.14, c=
Ca=123, b=3.00, c=A
D编译错误
✓ 选 A:%.2f 保留两位小数,c 读到字符 A。
C++ 格式化输入输出

cout 精度:setprecision 与 fixed

需要 #include <iomanip>
#include <iomanip> double pi = 3.14159265358979; cout << setprecision(4) << pi << endl; cout << fixed << setprecision(2) << pi << endl; cout << fixed << setprecision(6) << pi << endl;
运行结果
3.142 3.14 3.141593
i
默认 setprecision 管有效数字,加上 fixed 后管小数点后位数。
C++ 浮点数精度

float 与 double:第 7 位开始分家

程序
float f = 1.0 / 3.0; double d = 1.0 / 3.0; cout << fixed << setprecision(20); cout << "float: " << f << endl; cout << "double: " << d << endl;
运行结果
终端
float: 0.33333334326744079590 double: 0.33333333333333331483
i
float 约 7 位有效数字,double 约 15 位,高精度用 double。
C++ 浮点数精度

浮点比较:别用 ==,用 fabs 判差

错误:直接 ==
double a = 0.1 + 0.2; double b = 0.3; if (a == b) cout << "相等";
结果不一定相等:0.1+0.2 ≠ 0.3
正确:判断差是否足够小
double a = 0.1 + 0.2; double b = 0.3; if (fabs(a - b) < 1e-9) cout << "相等";
用 fabs(a-b) < 1e-9 判近似相等
!
浮点有精度限制,几乎不该直接 == 判断相等——改成判差值小于一个很小的数。
C++ 格式化输入输出

%0md:把日期和时间对齐整齐

代码
printf("%04d-%02d-%02d\n", 2023, 11, 5); printf("%02d:%02d:%02d\n", 15, 30, 25);
运行窗口
2023-11-05 15:30:25
%02d 的作用
%04d → 5 写成 "0005" %02d → 9 写成 "09"
i
%md 中 m 是总宽度,不足用 0 补(%0md),日期时间用 %04d-%02d-%02d 很整齐。
练一练

x = 12.3456789,两个输出都是什么?

程序
double x = 12.3456789; cout << fixed << setprecision(2) << x << endl; printf("%08.2f\n", x);
程序的输出是什么?
A12.35 00012.35
B12.35 0012.35
C12.35 012.35
D12.3456789 12.35
✓ 选 A:12.35(两位小数),%08.2f 总宽 8、补零得 00012.35。
03
PART 03 · 习题篇

综合挑战

用今天的知识,解两道关于浮点输出与百分号的题目。

浮点除法 保留小数 百分号 %%
习题讲解

两道浮点题:注意类型与格式

计算分数的浮点数值
double a, b; cin >> a >> b; printf("%.9f\n", b / a);
保留 9 位小数,用 double 存
输出保留 3 位小数的浮点数
float a; cin >> a; printf("%.3f\n", a);
注意:题目要求 float 类型
%
想输出百分号 %,要写 %%——因为 % 在格式串里是特殊字符。
小结

今天你学会了:

自增与自减
前缀 / 后缀取值 复合赋值 += 字符自增 优先级
格式化输入输出
scanf / & printf 特殊格式 %md cout 精度
浮点与习题
float / double fabs 比较 %0md 日期 百分号 %%
大卫信奥 · J1 知识点 · 五单元
05

习题课

综合运用前几单元知识——数据范围、格式化输出、除法与求余。

例题讲解 挑战题 · 分糖果
习题课封面
今日路线

三类内容,把前面学过的知识串起来

01
例题讲解
四舍五入、并联电阻、等差数列、浮点数求余。
02
挑战题
小朋友分糖果——一步步模拟过程。
03
小结
回顾知识点,完成课后练习。
01
PART 01 · 例题讲解

把四道例题讲透

格式化输出、浮点运算、数列计算、求余——逐个击破。

四舍五入 并联电阻 等差数列 浮点数求余
例题 1 · 明确舍入规则

半值远离 0:用 llround 得到整数

#include <bits/stdc++.h> using namespace std; int main() { double x; cin >> x; cout << llround(x) << endl; return 0; }
课堂约定:|x| ≤ 10¹²

llround 的结果可放入 long long。
3.6 → 4,3.4 → 3
2.5 → 3,−2.5 → −3

!
printf("%.0f") 是格式化输出,其半值处理不能直接等同于本题规则。x+0.5 再截断的方法只适用于限定范围内的非负数。
例题 2 · 计算并联电阻的阻值

R = 1 / (1/r1 + 1/r2):先倒数,再求和,再取倒数

两个电阻并联
r1
r2
R
R = 1 / (1/r1 + 1/r2)
先算倒数 → 加起来 → 再取倒数
#include <bits/stdc++.h> using namespace std; int main() { double r1, r2; cin >> r1 >> r2; double r = 1 / (1/r1 + 1/r2); printf("%.2f\n", r); return 0; }
输入:2 2 → 输出:1.00
1/(1/2+1/2)=1/(1)=1.00
例题 3 · 等差数列末项计算

先找公差 d,再用公式求第 n 项

公式卡片
an = a1 + (n − 1) × d
第 n 项 = 首项 + (项数 − 1) × 公差
d
公差 d = a2 − a1:相邻两项的差。
#include <bits/stdc++.h> using namespace std; int main() { int a1, a2, n; cin >> a1 >> a2 >> n; int d = a2 - a1; // 公差 int an = a1 + (n - 1) * d; // 末项 printf("%d\n", an); return 0; }
输入:2 5 4 → 输出:11
d=3,a4=2+3×3=11
例题 4 · 浮点余数

用 fmod 求近似余数,避免把大商转成 int

#include <bits/stdc++.h> using namespace std; int main() { double a, b; cin >> a >> b; cout << fmod(a, b) << endl; return 0; }
输入:7.5 2 输出:1.5
输入为有限浮点数,b ≠ 0

定义使用向 0 截断的商:
r = a − trunc(a/b) × b

!
fmod 是数学库函数,类似此前的 fabs。结果仍可能有浮点误差;整数 % 只用于整数,不能把任意大小的商强转 int。
02
PART 02 · 挑战题

小朋友分糖果

用变量和模拟,一步步还原一次分糖果的过程。

题意分析 编写模拟 运行验证
挑战题 · 小朋友分糖果

5 位小朋友围圆桌,依次把糖果分 3 份

1
2
3
4
5
①
把糖果均分成 3 份,有多余的,自己吃掉。
②
自己留 1 份。
③
另外 2 份分给左、右两边邻居。
④
从 1 号到 5 号 依次各做一次,正好一圈。
挑战题 · 编写模拟(一)

读入糖果,从 1 号开始轮流“分 3 份”

#include <bits/stdc++.h> // 通用头文件 using namespace std; int main() { int a, b, c, d, e; // 5 位小朋友的糖果 cin >> a >> b >> c >> d >> e; // 输入初始糖果 int t = 0; // t:吃掉的糖果总数 // 1 号:分 3 份,留 1 份,左右各 1 份 t = t + a % 3; // 多余的糖果吃掉 a = a / 3; b += a; e += a; // 留一份,给 b 和 e // 2 号 t = t + b % 3; // 多余的糖果吃掉 b = b / 3; a += b; c += b; // 留一份,给 a 和 c // 3 号 t = t + c % 3; // 多余的糖果吃掉 c = c / 3; b += c; d += c; // 留一份,给 b 和 d
挑战题 · 编写模拟(二)

接上一页:4、5 号再分,最后输出答案

// 4 号 t = t + d % 3; // 多余的糖果吃掉 d = d / 3; c += d; e += d; // 留一份,给 c 和 e // 5 号 t = t + e % 3; // 多余的糖果吃掉 e = e / 3; d += e; a += e; // 留一份,给 d 和 a // 输出答案 cout << a << ' ' << b << ' ' << c << ' ' << d << ' ' << e << endl; cout << t; // 吃掉的糖果总数 return 0; }
挑战题 · 运行验证

输入 10 10 10 10 10,一轮后变成了多少?

运行窗口
输入:10 10 10 10 10 输出:12 8 8 9 5 吃掉的糖果总数:8
!
模拟顺序:1→2→3→4→5,每个人分到的邻居糖果会叠加。
一轮结束后每人手里的糖果
a
12
b
8
c
8
d
9
e
5
t
吃掉的糖果总数 t = 8:1 号到 5 号吃掉的部分加起来。
03
PART 03 · 小结

这一节的关键

回顾今天用到的知识点,准备好课后练习。

精确输出 数据类型 求余 模拟
小结

今天你学会了:

格式化输出
printf("%.0f") printf("%.2f") printf("%d")
数据与运算
llround 半值远离 0 double 存小数 整数除法取整 % 取余 fmod 浮点求余
模拟思维
按顺序模拟 边模拟边统计 拆成小步骤
大卫信奥 · J1 知识点 · 六单元
06

关系运算符与 if 分支

用六种关系运算符比较大小,让程序学会“做判断”:if 与 if-else。

关系运算符 bool 转换 if / else 代码缩进
关系运算符与 if 分支封面
今日路线

四个环节,从“比较”走到“做出选择”

01
关系运算
六种运算符,结果只有 true / false。
02
bool 与转换
真与假,本质是 1 和 0,可隐式转换。
03
if / else
条件成立做什么,不成立又做什么。
04
代码规范
良好的缩进让代码结构一目了然。
06
PART 01 · 关系运算

让程序学会比大小

关系运算符比较两个值,结果永远是 true 或 false。

== != > < >= <= bool 结果
关系运算符

六种关系运算符:比较两个值

运算符含义例子结果
==等于5 == 5true(1)
!=不等于5 != 3true(1)
>大于10 > 5true(1)
<小于3 < 5true(1)
>=大于等于5 >= 5true(1)
<=小于等于3 <= 5true(1)
=
注意:== 才是比较,单个 = 是赋值。关系运算的结果是 bool:真 → 1,假 → 0。
练一练

a = 5, b = 10:六个比较的结果是什么?

程序
cout << (a == b) << endl; cout << (a != b) << endl; cout << (a > b) << endl; cout << (a < b) << endl; cout << (a >= b) << endl; cout << (a <= b) << endl;
程序的输出是什么?
A0 1 0 1 0 1
B0 1 0 1 1 0
C1 0 1 0 1 0
D1 0 0 1 0 1
✓ 选 A:a==b 为假(0),a!=b 为真(1),a>b 假(0),a<b 真(1),a>=b 假(0),a<=b 真(1)。
关系运算和 bool

比较的结果就是 bool:真 1 / 假 0

关系运算 → bool
bool r = (10 > 5); // r = true bool t = (10 == 5); // t = false cout << r << " " << t; // 输出 1 0
和整数互转
int i = true; // i = 1 int j = false; // j = 0 bool b = 42; // 非 0 → true bool c = 0; // 0 → false
!
非 0 值为真,0 为假——bool 参与运算时按 1 / 0 计算。
练一练

bool a = 42, b = 0;最后输出是什么?

程序
bool a = 42, b = 0; int c = a + b + true; cout << a << " " << b << " " << c << endl;
程序的输出是什么?
A1 0 2
B42 0 43
Ctrue false 2
D1 0 42
✓ 选 A:42 转成 true(1),0 转成 false(0),c = 1 + 0 + 1 = 2。
02
PART 02 · 运算符优先级

谁先算,谁后算

运算符优先级决定表达式的分组——记不住就用括号。

括号最高 算术 > 关系 > 相等 赋值最低
J1 常用运算符优先级

优先级决定表达式如何分组

层级运算符说明
1( )显式分组
2a++ a--后缀自增/自减
3++a --a ! + −前缀与一元运算符
4* / %乘、除、取模
5+ −加、减
6< <= > >=关系比较
7== !=相等性比较
8= += −= *= /= %=赋值类,右结合
!
本表只列 J1 常用项;前缀 ++/-- 与 !、一元正负号同层。括号改变分组,不普遍保证操作数或副作用的执行先后。
练一练

a=5, b=3, c=2:result 是多少?

程序
int a = 5, b = 3, c = 2; int result = a + b * c - a / c; cout << result << endl;
程序的输出是什么?
A9
B8
C13
D14
✓ 选 A:5 + 3×2 − 5÷2 = 5 + 6 − 2 = 9(整型除法 5/2 得 2)。
03
PART 03 · 分支语句

程序学会“做选择”

if 让程序根据条件走不同路径——这是编程里最基本、最重要的控制结构。

if if-else 嵌套
if 语句

if (条件) { 条件成立时执行 }

基本语法
if (条件) { // 条件为真时执行这里 }
条件为假时,整块代码被跳过。
例子:判断是否成年
int age = 20; if (age >= 18) { cout << "成年" << endl; } // 输出:成年
#
条件用括号括起来;只有一条语句时可省花括号,但建议始终写,代码更清晰。
练一练

score = 85,输出是什么?

程序
int score = 85; if (score >= 60) { cout << "及格" << endl; } if (score >= 90) { cout << "优秀" << endl; }
程序的输出是什么?
A及格
B优秀
C及格 优秀
D没有输出
✓ 选 A:两个独立的 if——85 ≥ 60 成立输出“及格”,85 ≥ 90 不成立跳过。
if-else 语句

if-else:条件真假,各走一条路

语法
if (条件) { // 真:执行这里 } else { // 假:执行这里 }
例子:奇偶判断
int num = 9; if (num % 2 == 0) { cout << "偶数"; } else { cout << "奇数"; // 输出:奇数 }
!
if-else 必走其一:条件真执行 if 块,假执行 else 块,不会两个都执行。
练一练

num = -5,输出是什么?

程序
int num = -5; if (num > 0) { cout << "正数" << endl; } else { cout << "非正数" << endl; }
程序的输出是什么?
A正数
B非正数
C0
D没有输出
✓ 选 B:-5 不大于 0,走 else 分支输出“非正数”。
嵌套判断

先判断大条件,再进入小分支

int num; cin >> num; if (num > 0) { if (num % 2 == 0) cout << "正偶数"; else cout << "正奇数"; } else { cout << "非正数"; }

先问“是正数吗?”
是 → 再问“是偶数吗?”
否 → 输出“非正数”。

!
花括号明确每个 else 属于哪个 if。输入 4 / 3 / 0 分别得到正偶数、正奇数、非正数。
04
PART 04 · 代码规范与习题

代码是写给人看的

良好的缩进让 if 结构一目了然,最后用两道题检验今天所学。

缩进习惯 奇偶判断 输出绝对值
代码格式与缩进

缩进:让代码块“一眼看出”嵌套关系

好缩进 · 清晰
if (x > 5) { cout << "大"; if (x > 8) { cout << "更大"; } }
坏缩进 · 难读
if (x > 5) { cout << "大"; if (x > 8) { cout << "更大"; } }
!
每进入一层花括号就缩进 2 或 4 个空格,整份代码保持统一。
习题讲解

两道题:奇偶判断与输出绝对值

奇偶判断 · even / odd
int num; cin >> num; if (num % 2 == 0) { cout << "even" << endl; } else { cout << "odd" << endl; }
num % 2 == 0 → 偶数,否则奇数
输出绝对值 · 保留两位小数
double num; cin >> num; if (num < 0) { cout << fixed << setprecision(2) << -num << endl; } else { cout << fixed << setprecision(2) << num << endl; }
负数取相反数,再按两位小数输出
#
判断类的题:先想清楚“条件”是什么,再决定 if / else 里各写什么。
小结

今天你学会了:

关系运算
== != > < >= <= 结果是 bool 非 0 为真
优先级
括号最高 算术 > 关系 > 相等 赋值最低
分支与规范
if if-else 统一缩进
大卫信奥 · J1 知识点 · 七单元
07

逻辑运算符与多分支

用 && || ! 组合条件,学会 if-else 多分支和 switch 语句。

逻辑运算 优先级 多分支 switch
逻辑运算符与多分支封面
今日路线

四个环节,从“组合条件”走到“多路选择”

01
逻辑运算
&&、||、! 三个运算符组合条件。
02
优先级
逻辑运算插入常用优先级表。
03
多分支
if-else if-else:从上到下匹配。
04
switch
按值跳转,小心“贯穿”。
01
PART 01 · 逻辑运算符

把条件组合起来

一个条件不够用?用 && || ! 把多个条件拼成一句话。

&& 与 || 或 ! 非
逻辑运算符

与、或、非:三种逻辑运算

&&
逻辑与
两个都真才真
||
逻辑或
一个真就真
!
逻辑非
真假颠倒
true && false → 0 false && false → 0 true && true → 1
false || false → 0 false || true → 1 true || true → 1
!true → 0 !false → 1 !0 → 1
!
短路求值:&& 左边为假就不再算右边;|| 左边为真也一样——可避免除以零等错误。
逻辑运算符

组合条件:一个 if 管多个条件

int age = 25; bool hasID = true; cout << (age >= 18 && hasID); // 1 int score = 85; cout << (score >= 60 || score == -1); // 1 bool rain = true; cout << !rain; // 0
&&
age >= 18 && hasID:年龄够且带证件,才能投票(1)。
||
score >= 60 || score == -1:及格或免考,都算通过(1)。
!
!rain:下雨的反面是不下雨,结果 0。
练一练

a = true, b = false:四个输出是什么?

程序
cout << (a && b) << endl; cout << (a || b) << endl; cout << (!a) << endl; cout << (!b) << endl;
程序的输出是什么?
A0 1 0 1
B0 1 1 0
Cfalse true false true
Dfalse true true false
✓ 选 A:&& 全真才真(0),|| 一真即真(1),!a 为 0,!b 为 1。
02
PART 02 · 完整的优先级

逻辑运算也要排队

加上逻辑运算后的常用优先级:! 很高,&& 高于 ||,赋值还是最低。

! 一元 && > || 赋值最低
J1 常用运算符优先级

优先级决定表达式如何分组

层级运算符说明
1( )显式分组
2a++ a--后缀自增/自减
3++a --a ! + −前缀与一元运算符
4* / %乘、除、取模
5+ −加、减
6< <= > >=关系比较
7== !=相等性比较
8&&逻辑与
9||逻辑或
10= += −= *= /= %=赋值类,右结合
!
本表只列 J1 常用项;前缀 ++/-- 与 !、一元正负号同层。括号改变分组,不普遍保证操作数或副作用的执行先后。
练一练

a=5, b=3, c=10:result 是多少?

程序
bool result = a > b && a < c || a == b; cout << result << endl;
程序的输出是什么?
A0
B1
Ctrue
Dfalse
✓ 选 B:a>b 真 && a<c 真 → 真;真 || (a==b 假) → 真,输出 1。
03
PART 03 · 多分支

不止两条路

条件再多也不怕:if-else if-else 从上往下匹配,命中即止。

else if 顺序很重要 嵌套
if-else if-else

多分支:从上到下,命中即停

if (条件1) { // 条件1 真:执行 } else if (条件2) { // 条件1 假、条件2 真:执行 } else if (条件3) { // 前两个都假、条件3 真:执行 } else { // 全不满足:执行 }
成绩评级例
int score = 85; if (score >= 90) cout << "优秀"; else if (score >= 80) cout << "良好"; else if (score >= 70) cout << "中等"; else if (score >= 60) cout << "及格"; else cout << "不及格";
!
条件从上到下依次检查,命中一个就跳出——更严格的条件要放前面。
练一练

score = 75,输出什么等级?

程序
if (score >= 90) cout << "A"; else if (score >= 80) cout << "B"; else if (score >= 70) cout << "C"; else if (score >= 60) cout << "D"; else cout << "F";
程序的输出是什么?
AA
BB
CC
DD
✓ 选 C:75 ≥ 90 假、≥ 80 假、≥ 70 真 → 输出 C,后面不再判断。
04
PART 04 · switch 语句

按值跳转

一个变量等于几,就进哪个 case——多分支的另一种写法。

case break default
switch 语句

switch:值匹配哪个 case,进哪个

基本语法
switch (表达式) { case 常量1: /* 匹配时执行 */ break; case 常量2: /* ... */ break; default: /* 都不匹配 */ break; }
星期例
switch (day) { case 1: cout << "周一"; break; case 2: cout << "周二"; break; case 3: cout << "周三"; break; case 4: cout << "周四"; break; case 5: cout << "周五"; break; case 6: cout << "周六"; break; case 7: cout << "周日"; break; default: cout << "无效"; }
输入 3 → 输出“周三”;输入 9 → “无效”
!
case 后必须是常量;忘记 break 会“贯穿”到下一个 case;default 可有可无。
贯穿 (fall-through)

没写 break:一路滑到下一个 case

choice = 2
switch (choice) { case 1: cout << "One"; break; case 2: cout << "Two"; // 无 break case 3: cout << "Three"; break; }
输出:Two 然后继续执行 → Three
有意利用:多个 case 共用代码
switch (grade) { case 'A': case 'B': case 'C': cout << "及格"; break; case 'D': case 'F': cout << "不及格"; break; }
#
写 switch 时先想清楚每个 case 末尾要不要 break——贯穿是常见 bug,但也能有意利用。
练一练

choice = 2,输出是什么?

程序
switch (choice) { case 1: cout << "One"; break; case 2: cout << "Two"; case 3: cout << "Three"; break; default: cout << "Other"; }
程序的输出是什么?
AOne
BTwo
CThree
DTwoThree
✓ 选 D:case 2 没有 break,贯穿到 case 3 输出 TwoThree 才停。
分支选型

按常量值跳转,还是按条件判断?

需求适合写法例子
整数或枚举值匹配一组不同常量switch星期 1~7、字符 A/B/C
区间与组合条件if / else ifscore ≥ 90、x>0 && y>0
多个常量共用一段处理多个 case 标签有意共用分支,末尾按需 break
!
switch 不能直接按浮点数或 std::string 匹配;case 必须是允许的常量表达式且不能重复。
小结

今天你学会了:

逻辑运算
&& || ! 短路求值 组合条件
优先级
! 比算术高 && > || 赋值最低
多分支
else if 从上到下 switch / case break 与贯穿
大卫信奥 · J1 知识点 · 八单元
08

条件运算符与综合练习

用 ?: 一行写完分支选择,最后综合运用 if 做几道完整题目。

条件运算符 常用优先级 结合性 if 综合练习
条件运算符与综合练习封面
今日路线

三个环节,把运算符与分支彻底打通

01
条件运算符
?: 三目运算,一行写分支。
02
常用优先级
J1 常用运算符 + 结合性 + 一般规律。
03
综合练习
几何、计算器、分段函数四道主课题,另有两道选做。
01
PART 01 · 条件运算符

一行写完的分支

条件 ? 真值 : 假值——C++ 里唯一的三目运算符。

? : 嵌套使用 与 if-else 对比
条件运算符

条件 ? 表达式1 : 表达式2

工作原理
条件真 → 取表达式1 条件假 → 取表达式2
整个 ?: 是一个“表达式”,不是语句
例:取较大值
int a = 10, b = 20; int max = (a > b) ? a : b; cout << max; // 20
x >= 0 ? "非负数" : "负数" 也行
?
条件运算符是 if-else 的简化:只选一个值时简洁清晰;逻辑复杂时还是用 if-else。
练一练

a=3, b=5:两个输出是什么?

程序
cout << ((a > b) ? a : b) << endl; cout << ((a < b) ? a : b) << endl;
程序的输出是什么?
A3 3
B5 3
C3 5
D5 5
✓ 选 B:a>b 假取 b=5,a<b 真取 a=3。
02
PART 02 · 常用优先级

一张表整理常用运算符

优先级 + 结合性 + 一般规律——分组与实际执行先后分别分析。

分清前缀与后缀 左结合为主 括号明确分组
J1 常用运算符优先级

优先级决定表达式如何分组

层级运算符说明
1( )显式分组
2a++ a--后缀自增/自减
3++a --a ! + −前缀与一元运算符
4* / %乘、除、取模
5+ −加、减
6< <= > >=关系比较
7== !=相等性比较
8&&逻辑与
9||逻辑或
10? :条件运算符
11= += −= *= /= %=赋值类,右结合
!
本表只列 J1 常用项;前缀 ++/-- 与 !、一元正负号同层。括号改变分组,不普遍保证操作数或副作用的执行先后。
结合性

同级运算符:从左还是从右?

左结合 · 大多数
a - b - c 也就是 (a - b) - c a / b / c 等价于 (a / b) / c
右结合 · 赋值与一元
a = b = c 也就是 a = (b = c) !!a 等价于 !(!a)
!
a < b < c 是新手坑:先得 0 或 1,再和 c 比——这样写不如拆成 a < b && b < c。
练一练

a=5, b=3:两个输出是什么?

程序
cout << a + b * 2 << endl; cout << (a + b) * 2 << endl;
程序的输出是什么?
A11 16
B16 11
C13 16
D16 13
✓ 选 A:先乘后加 5+6=11;括号先加 (5+3)×2=16。
03
PART 03 · 综合练习

把分支用起来

四道主课题:几何判断、计算器、分段函数——都是高频 OJ 题型。

点与正方形 三角形判断 简单计算器 分段函数
综合练习 · 点和正方形

点 (x, y) 在正方形 (-1~1) 内吗?

int x, y; cin >> x >> y; if (x >= -1 && x <= 1 && y >= -1 && y <= 1) { cout << "yes" << endl; } else { cout << "no" << endl; }
输入:1 1 输出:yes 输入:2 0 → no
&&
四个条件同时满足才在正方形内:x 和 y 都要在 [-1, 1]。
=
边界也算:>= 与 <= 把四条边包含进来。
综合练习 · 三角形判断

三条边能构成三角形吗?

int a, b, c; cin >> a >> b >> c; if (a + b > c && a + c > b && b + c > a) { cout << "yes" << endl; } else { cout << "no" << endl; }
输入:3 4 5 输出:yes 输入:1 2 3 → no
Δ
任意两边之和 > 第三边,三组都要成立——用 && 连接。
!
1 + 2 = 3 正好相等也不行——等于不能构成,必须严格大于。
综合练习 · 简单计算器

计算器:+ - * /,还有两种错误

int a, b; char op; cin >> a >> b >> op; if (op == '+') { cout << a + b << endl; } else if (op == '-') { cout << a - b << endl; } else if (op == '*') { cout << a * b << endl; } else if (op == '/') { if (b == 0) cout << "Divided by zero!"; else cout << a / b << endl; } else { cout << "Invalid operator!" << endl; }
输入:1 2 + → 3
输入:1 0 / → Divided by zero!
!
除数为 0 必须先判断,再进入除法——嵌套 if 解决。
综合练习 · 分段函数

先写题目与区间,再选择公式

输入:浮点数 0 ≤ x < 20。
输出:y,保留 3 位小数。

区间y 的值
0 ≤ x < 5−x + 2.5
5 ≤ x < 102 − 1.5(x−3)²
10 ≤ x < 20x/2 − 1.5
输入:1.0 输出:1.500
double x; cin >> x; double y; if (x >= 0 && x < 5) { y = -x + 2.5; } else if (x >= 5 && x < 10) { y = 2 - 1.5 * (x - 3) * (x - 3); } else if (x >= 10 && x < 20) { y = x / 2 - 1.5; } cout << fixed << setprecision(3) << y << endl;
课后选做 1

把时间模型写成可比较的表达式

骑车准备与停车共 50 秒,速度 3m/s;步行速度 1.2m/s。
输入非负整数距离 d(≤10⁶),输出 Bike / Walk / All。

!
把两种时间都乘 6:步行是 5d,骑车是 300+2d,比较结果不变。
d=100 → All;d=120 → Bike
int distance; cin >> distance; // 非负整数,单位米 long long walk6 = 5LL * distance; long long bike6 = 300 + 2LL * distance; if (bike6 < walk6) cout << "Bike"; else if (bike6 > walk6) cout << "Walk"; else cout << "All";
课后选做 2

不足一档,按一档收费

1000 克以内 8 元;超出部分每 500 克收 4 元,不足 500 克也算一档;加急再收 5 元。
输入重量和 y/n,输出整数邮费。

!
正整数 x 按 500 向上取整: (x+499)/500。边界检查 1000、1001、1500、1501。
输入:1200 y → 17
int weight; char express; cin >> weight >> express; // 1 <= weight <= 1e6 int cost = 8; if (weight > 1000) cost += (weight - 1000 + 499) / 500 * 4; if (express == 'y') cost += 5; cout << cost << endl;
小结

今天你学会了:

条件运算符
条件 ? a : b 结果是个表达式 可嵌套
常用优先级
分清前缀与后缀全表 左结合为主 括号明确分组
综合练习
判断几何关系 嵌套 if 分段函数
大卫信奥 · J1 知识点 · 九单元
09

for 循环

重复的任务交给计算机——认识 for 的结构、应用、变形与控制,最后综合实战。

循环结构 数字序列 嵌套循环 break · continue
for 循环封面
今日路线

三程推进,把 for 循环拿下

01
循环入门
为什么需要循环 + for 的语法结构 + 执行流程。
02
基本应用
数字序列、累加求和、阶乘——循环三板斧。
03
变形与综合
倒序/步长/嵌套,break/continue 与综合练习。
01
PART 01 · 循环入门

为什么需要循环

重复任务交给计算机——认识 for 的结构与执行流程。

重复任务 语法结构 执行流程
循环的概念

循环 = 按规则重复执行同一段代码

日常中的重复
数数:1、2、3、4、5……
反复练习写字
按规律输出一系列数据
for 循环擅长
✓ 已知循环次数
✓ 按顺序处理数据
✓ 生成有规律的序列
?
想一想
输出 1 到 100 的数字:不用循环要写 100 行代码,for 循环只要几行。
for 的结构

for (初始化; 条件; 更新) { 循环体 }

语法骨架
for (初始化表达式; 条件表达式; 更新表达式) { 循环体语句; }
第一个例子:喊五遍
for (int i = 1; i <= 5; i++) { cout << "这是第" << i << "次循环" << endl; } cout << "循环结束" << endl;
这是第1次循环 … 这是第5次循环 → 循环结束
部分代码含义
初始化int i = 1定义循环变量 i 并赋值为 1
条件i <= 5i 小于等于 5 时继续循环
更新i++每次循环后 i 自增 1
执行流程

for 循环怎么一步步跑?

1
初始化
执行初始化表达式(整个循环只执行一次)
2
条件判断
真 → 进入循环体;假 → 循环结束
3
循环体 + 更新
执行循环体语句,再执行更新表达式,回到第 2 步
!
重要
循环变量 i 就像一个计数器,帮助我们记录当前是第几次循环。
02
PART 02 · 基本应用

三个练习打底

数字序列、累加求和、阶乘——每个都要上手敲一遍。

数字序列 累加求和 阶乘
练习 · 数字序列输出

输出 1 到 10 的数字

cout << "输出1到10的数字:"; for (int i = 1; i <= 10; i++) { cout << i << " "; } cout << endl;
输出1到10的数字:1 2 3 4 5 6 7 8 9 10
✎
动手练习:
① 改成输出 1 到 20
② 输出 10 倒数到 1(提示:改初始值、条件和更新)
练习 · 累加计算

1 + 2 + 3 + 4 + 5 = ?

int sum = 0; // 用来存储累加和 for (int i = 1; i <= 5; i++) { sum += i; // 等价于 sum = sum + i cout << "加上" << i << "后,总和为:" << sum << endl; } cout << "1+2+3+4+5 = " << sum << endl;
运行结果
加上1后,总和为:1
加上2后,总和为:3
加上3后,总和为:6
加上4后,总和为:10
加上5后,总和为:15
最终结果:1+2+3+4+5 = 15
+
累加套路:sum = 0 起步,循环里 sum += i。
练习 · 阶乘计算

5! = 5 × 4 × 3 × 2 × 1

int n = 5; int factorial = 1; for (int i = 1; i <= n; i++) { factorial *= i; // factorial = factorial * i cout << i << "! = " << factorial << endl; }
运行结果
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
×
阶乘起步必须是 1;乘的顺序是从 1 乘到 n。
03
PART 03 · 变形与控制

循环的七十二变

倒序、步长、嵌套——再学会 break 与 continue 两个控制开关。

倒序 步长 嵌套 break / continue
倒序循环

从 10 倒数到 1

cout << "倒计时:"; for (int i = 10; i >= 1; i--) { cout << i << " "; } cout << "开始!" << endl;
倒计时:10 9 8 7 6 5 4 3 2 1 开始!
↓
倒序三件套:
初始值给大 i = 10
条件用 >= 或 >
更新改 i--
步长循环

不一定要 +1,可以跳着走

cout << "2到20的偶数:"; for (int i = 2; i <= 20; i += 2) { // 每次加2 cout << i << " "; } cout << endl;
2到20的偶数:2 4 6 8 10 12 14 16 18 20
±
i += 2 就是步长为 2。
步长可以是任意整数,i += 3、i *= 2 都行。
嵌套循环

循环里面再套循环:乘法表

for (int i = 1; i <= 3; i++) { for (int j = 1; j <= 3; j++) { cout << i << "×" << j << "=" << i*j << "\t"; } cout << endl; }
1×1=1 1×2=2 1×3=3
2×1=2 2×2=4 2×3=6
3×1=3 3×2=6 3×3=9
×
外层每走一次,内层完整跑一遍。
外层 i 控制行,内层 j 控制列。
练一练

下面嵌套循环会输出什么?

程序
for (int i = 0; i < 3; i++) { for (int j = 0; j < 2; j++) { cout << i << j << " "; } }
程序的输出是什么?
A00 01 10 11 20 21
B00 10 20 01 11 21
C01 02 11 12 21 22
D12 34 56
✓ 选 A:外层循环变 i,内层循环变 j,每轮 i 固定、j 从 0 到 1。
break 语句

找到目标就停:break

cout << "寻找第一个能被7整除的数:" << endl; for (int i = 1; i <= 100; i++) { if (i % 7 == 0) { cout << "找到了:" << i << endl; break; // 找到后立即结束循环 } } cout << "搜索结束" << endl;
找到了:7 → 搜索结束
■
break 立即结束整个循环,不再执行后面的循环体。
适合"找到目标就不需要继续"的情况。
continue 语句

跳过这一次:continue

cout << "1到10中除了5以外的数:"; for (int i = 1; i <= 10; i++) { if (i == 5) { continue; // 跳过5,继续下一次循环 } cout << i << " "; } cout << endl;
1到10中除了5以外的数:1 2 3 4 6 7 8 9 10
⏭
continue 跳过本轮剩余语句,先执行更新表达式 i++,再判断条件,进入下一轮。
对比

break vs continue:一个跳出,一个跳过

语句作用效果
break立即结束整个循环直接跑到循环后面的代码
continue跳过当前循环的剩余部分for:先更新,再判断;while/do-while:转到条件判断
应用:只输出偶数
for (int i = 1; i <= 20; i++) { if (i % 2 != 0) continue; // 奇数跳过 cout << i << " "; }
区分记忆
break → 整层循环终止
continue → 本轮跳过,循环继续
练一练

下面代码输出什么?

程序
for (int i = 1; i <= 6; i++) { if (i % 2 == 0) continue; if (i == 5) break; cout << i << " "; }
程序的输出是什么?
A1 3
B1 3 5
C2 4 6
D1 2 3 4 5
✓ 选 A:偶数被 continue 跳过;到 i=5 时 break 提前结束(5 和 6 都不输出)。
04
PART 04 · 综合练习

把 for 用起来

数字翻转、水仙花数——经典的循环 + 数位分离题型。

数字翻转 水仙花数 编程挑战
综合练习 · 数字翻转

1234 翻转成 4321

int number = 1234; int reversed = 0; for (int temp = number; temp > 0; temp /= 10) { int digit = temp % 10; // 取最后一位 reversed = reversed * 10 + digit; } cout << "翻转后:" << reversed << endl;
原数字:1234 → 翻转后:4321
%
数位分离两件套:
% 10 取个位
/ 10 去掉个位
综合练习 · 水仙花数

三位水仙花数有哪些?

for (int num = 100; num <= 999; num++) { int a = num / 100; // 百位 int b = (num / 10) % 10; // 十位 int c = num % 10; // 个位 if (a*a*a + b*b*b + c*c*c == num) { cout << num << " "; } }
三位水仙花数:153 370 371 407
✿
水仙花数:各位数字的立方和等于它本身。
先拆位,再判断。
编程挑战

敢不敢先自己写?

挑战 1
输入一个数 n,计算 1² + 2² + … + n²(1 到 n 的平方和)。
挑战 2
判断一个四位数是否是四叶玫瑰数(各位数字的四次方和等于本身)。
小结

今天你学会了:

for 结构
初始化 · 条件 · 更新 先判断后执行 循环变量是计数器
变形
倒序 i-- 步长 i += k 嵌套循环
控制语句
break 结束循环 continue 跳过本轮 数位分离 % /
大卫信奥 · J1 知识点 · 十单元
10

while 与 do-while 循环

条件说了算的循环——三种循环全家桶对比,加上嵌套与无限循环。

while do-while 循环对比 嵌套 · 无限循环
while 循环封面
今日路线

三个环节,把条件循环学透

01
while 循环
条件驱动:先判断、后执行,适合未知次数。
02
do-while + 对比
至少执行一次,三种循环一张表看明白。
03
高级应用
嵌套循环、无限循环、break/continue 通行。
01
PART 01 · while 循环

条件说了算

先判断条件再执行循环体——不知道要循环几次时最好用。

先判断后执行 累加求和 猜数字游戏
while 的概念

条件为真,就一直执行

while 的特点
✓ 先判断条件,再执行循环体
✓ 只要条件为真就一直执行
✓ 适合未知循环次数的场景
生活中的 while
只要饭锅里还有米饭,就继续吃
只要题目没做完,就继续做
只要水没烧开,就继续等
?
想一想
什么时候无法预先知道循环次数?等待用户输入特定的退出指令、处理长度不确定的数据……
while 的结构

while (条件) { 循环体 }

语法骨架 + 执行流程
while (条件表达式) { 循环体语句; }
① 条件判断 → ② 真就执行循环体 → ③ 回到 ①
直到条件为假,循环结束。
例子:喊五遍
int count = 1; while (count <= 5) { cout << "这是第" << count << "次循环" << endl; count++; // 更新循环变量 } cout << "循环结束" << endl;
这是第1次循环 … 第5次循环 → 循环结束
!
重要
必须在循环体内更新循环变量或条件,否则可能造成无限循环。
例 1 · 数字累加

用 while 算 1 到 10 的和

int i = 1; int sum = 0; while (i <= 10) { sum += i; cout << "加上" << i << "后,总和为:" << sum << endl; i++; } cout << "1到10的和是:" << sum << endl;
运行结果
加上1后,总和为:1
加上2后,总和为:3
…
加上10后,总和为:55
1到10的和是:55
i
for 的"初始化"搬到了循环外面,"更新"搬到了循环体里面。
例 2 · 猜数字游戏

while (!guessed) 猜到对为止

本例保证输入为整数;这里只验证数值范围。完整交互还需处理读入失败和 EOF。

int target = 42; int guess; bool guessed = false; cout << "猜一个1到100之间的数字:" << endl; while (!guessed) { cin >> guess; if (guess < target) { cout << "太小了,再试试:" << endl; } else if (guess > target) { cout << "太大了,再试试:" << endl; } else { cout << "恭喜你,猜对了!" << endl; guessed = true; } }
✎
动手练习:
① 限制猜测次数为 10 次
② 每次显示剩余次数
③ 10 次没猜对就公布答案
02
PART 02 · do-while

至少执行一次

先干活再问条件——菜单选择、输入验证的常客。

先执行后判断 菜单选择 输入验证
do-while 的结构

do { 循环体 } while (条件);

特点
① 先执行循环体
② 再判断条件
③ 条件为真回到 ①

至少执行一次,无论条件是否为真。
例子:喊五遍
int count = 1; do { cout << "这是第" << count << "次循环" << endl; count++; } while (count <= 5); // ⚠ 别忘了分号 cout << "循环结束" << endl;
这是第1次循环 … 第5次循环 → 循环结束
;
最容易漏的:do-while 的 while (条件) 后面要加分号。
例 1 · 菜单选择

菜单要显示一次,就要 do-while

本例保证输入为整数;这里只验证数值范围。完整交互还需处理读入失败和 EOF。

int choice; do { cout << "===== 菜单 =====" << endl; cout << "1. 查看信息" << endl; cout << "2. 修改设置" << endl; cout << "3. 退出程序" << endl; cout << "请输入选择:"; cin >> choice; switch (choice) { case 1: cout << "显示信息..." << endl; break; case 2: cout << "修改设置..." << endl; break; case 3: cout << "程序退出,再见!" << endl; break; default: cout << "无效选择,请重试" << endl; } } while (choice != 3);
☰
先显示菜单、再读选择——第一次必须执行,正是 do-while 的用武之地。
例 2 · 输入验证

不合法就再问一次

本例保证输入为整数;这里只验证数值范围。完整交互还需处理读入失败和 EOF。

int number; do { cout << "请输入一个正整数:"; cin >> number; if (number <= 0) { cout << "输入无效,必须是正整数!" << endl; } } while (number <= 0); cout << "你输入的正整数是:" << number << endl;
✎
练一练:把上面的程序改成验证输入是 1 到 100 之间的整数。
03
PART 03 · 三种循环对比

for / while / do-while 全家桶

一张表记住区别,再学会互相转换。

对比表 选型指南 互相转换
循环对比

三种循环一张表

循环执行顺序最少执行适用场景
for初始化→判断→循环体→更新0 次已知循环次数
while条件判断→循环体0 次未知次数 · 前测试
do-while循环体→条件判断1 次未知次数 · 后测试
?
核心区别只有一个:循环体最少执行几次——0 次(for/while)还是 1 次(do-while)。
选型与转换

什么时候用哪个?

for
已知次数、按顺序遍历、变量有明确初始值和规律。
while
不知道次数、条件复杂、靠条件决定是否继续。
do-while
必须至少执行一次:输入验证、菜单选择。
for → while:先说明 continue 的例外
// 本转换假定循环体没有 continue for (int i=1; i<=5; i++) { /* 循环体 */ } { // 保留 i 的作用域 int i=1; while (i<=5) { /* 循环体 */ i++; } }
04
PART 04 · 高级应用

循环的进阶玩法

嵌套、无限循环、break/continue——在任何循环里都好用。

嵌套循环 无限循环 break / continue
嵌套循环

三种循环可以互相嵌套

int i = 1; while (i <= 3) { // 外层 while cout << "外层循环 i = " << i << ": "; for (int j = 1; j <= 4; j++) { // 内层 for cout << j << " "; } cout << endl; i++; }
外层循环 i = 1: 1 2 3 4
外层循环 i = 2: 1 2 3 4
外层循环 i = 3: 1 2 3 4
⤴
while / do-while / for 任意组合都可以嵌套。
无限循环

条件永远为真:三种写法

while (true) { // 循环体 if (someCondition) break; }
for (;;) { // 循环体 if (someCondition) break; }
do { // 循环体 if (someCondition) break; } while (true);
!
警告
无限循环必须有退出机制(如 break),否则程序永远运行下去。
循环控制

break / continue 在哪都通用

while 中的 break
int i = 1; while (i <= 100) { if (i % 17 == 0) { cout << "找到第一个被17整除的数:" << i; break; } i++; }
do-while 中的 continue
int i = 0; do { i++; if (i % 3 == 0) continue; cout << i << " "; } while (i < 10);
运行结果
左侧:17
右侧跳过 3 的倍数:
1 2 4 5 7 8 10
小结

今天你学会了:

while 循环
先判断后执行 可能一次都不执行 记得更新循环变量
do-while 循环
先执行后判断 至少执行一次 条件后要有分号
对比与进阶
for 已知次数 while 条件控制 嵌套 · 无限循环
大卫信奥 · J1 知识点 · 十一单元
11

循环综合 · OJ 例题

把循环用在真题里:递推、数位分离、取模防溢出——学着拆解一类题。

递推 数位分离 取模 条件比较
循环综合例题封面
今日路线

七道例题,两类套路

01
循环与递推
人口增长、斐波那契、鸡尾酒疗法。
02
数位与取模
四位数统计、星期几、幂的末尾、含 k 个 3。
03
套路总结
把例题归纳成模板,下次直接套。
01
PART 01 · 循环与递推

一步一个脚印

增长率、斐波那契、有效率比较——循环往复数轮就能出答案。

人口增长 斐波那契 鸡尾酒疗法
例题 · 人口增长问题

每年增长 0.1%,n 年后多少人?

题面与要点
初始人口 e,年增长率 0.1%(乘 1.001),求 n 年后的结果。

考察:对增长率的理解 + 循环累乘。
输出保留 4 位小数 → printf 格式。
int n; double e; cin >> e >> n; for (int i = 1; i <= n; i++) { e = e * 1.001; } printf("%.4lf", e);
每一轮都乘 1.001,n 轮后输出
例题 · 斐波那契 · 一组查询核心

F₁=F₂=1,保存相邻两项

练习输入:先给 T,再给 T 个下标 a。
每个 a 满足 1 ≤ a ≤ 92。
每组输出一行 Fₐ。

!
long long 支持 F₉₂;F₉₃ 已超出常见 64 位有符号范围。右侧展示一组处理,完整程序包含 T 组循环。
int a; cin >> a; // 1 <= a <= 92 long long f1 = 1, f2 = 1; for (int i = 3; i <= a; i++) { long long f3 = f1 + f2; f1 = f2; f2 = f3; } cout << f2 << endl;
例题 · 鸡尾酒疗法 · 核心代码

用整数精确比较 5 个百分点

先输入 n ≥ 1,再输入 n 组“总人数 有效人数”。第一组是基准。
本页范围:总人数 1~10⁶,有效人数 0~总人数。

!
有效率差值 > 1/20 才是 better;< −1/20 才是 worse,恰好相差 5 个百分点为 same。交叉相乘的中间值在本范围内可放 long long。
基准 10 2,对比 20 3 → same
int n; cin >> n; long long a0, b0; cin >> a0 >> b0; for (int i = 1; i < n; i++) { long long a, b; cin >> a >> b; long long delta = 20 * (b*a0 - b0*a); long long base = a*a0; if (delta > base) cout << "better\n"; else if (delta < -base) cout << "worse\n"; else cout << "same\n"; }
02
PART 02 · 数位与取模

拆数字、控溢出

数位分离处理每一位,取模运算防止数据爆炸。

统计四位数 计算星期几 幂的末尾 含 k 个 3
例题 · 统计满足条件的 4 位数

个位 − 千位 − 百位 − 十位 > 0?

数位分离模板
a = x % 10(个位)
b = x / 10 % 10(十位)
c = x / 100 % 10(百位)
d = x / 1000(千位)

满足 a − d − c − b > 0 就计数。
int n, sum = 0; cin >> n; for (int i = 1; i <= n; i++) { int x, a, b, c, d; cin >> x; a = x % 10; b = x / 10 % 10; c = x / 100 % 10; d = x / 1000; if (a - d - c - b > 0) sum++; } cout << sum << endl;
读入 n 个数,逐个拆位、判断、计数
例题 · 星期几 · 核心代码

从周日开始,aᵇ 天后是星期几?

练习约定:0 ≤ a ≤ 10⁹,0 ≤ b ≤ 10⁶。
周日对应 0,周一对应 1,依此类推。

!
先将底数 a 对 7 取模,再逐次乘,乘法两数均很小。只在乘完后取模,无法补救已经发生的溢出。
输入:2 1 → Tuesday
long long a; int b; cin >> a >> b; int base = a % 7, day = 1; for (int i = 0; i < b; i++) day = day * base % 7; switch (day) { case 0: cout << "Sunday"; break; case 1: cout << "Monday"; break; case 2: cout << "Tuesday"; break; case 3: cout << "Wednesday"; break; case 4: cout << "Thursday"; break; case 5: cout << "Friday"; break; case 6: cout << "Saturday"; break; }
例题 · 幂的末尾

只要最后三位:% 1000

同款套路,只看末尾
只需要最后三位:
每乘一次就 % 1000。

输出要补零:
printf("%03d")
5 → 005,120 → 120
long long a; int b; cin >> a >> b; // 0 <= a <= 1e9, 0 <= b <= 1e6 a %= 1000; // 先缩小底数,避免乘法先溢出 int result = 1; for (int i = 0; i < b; i++) result = result * a % 1000; printf("%03d\n", result);
和"星期几"是同一个模板:取模保平安
例题 · 含 k 个 3 的数

非负整数逐位拆数(0 ≤ m ≤ 10¹⁸)

逐位处理模板
while (m) 循环直到 m = 0:
① digit = m % 10 取个位
② 统计 digit 是不是 3
③ m /= 10 去掉个位

数字可能很大 → 用 long long。
long long m; int k, count = 0; cin >> m >> k; while (m) { int digit = m % 10; if (digit == 3) count++; m /= 10; } if (count == k) cout << "YES" << endl; else cout << "NO" << endl;
拆完所有位,3 的个数刚好等于 k 就 YES
小结

今天你学会了:

递推模板
循环累乘 f3 = f1 + f2 滚动 int 除法要转 double
数位分离
% 10 取个位 / 10 去个位 for 或 while 都能拆
取模防溢出
边乘边 % % 7 算星期 % 1000 取末尾
大卫信奥 · J1 知识点 · 十二单元
12

数组

一个名字装下整组数据——声明、初始化、遍历、易错点和四道例题一次讲清。

声明与访问 初始化 遍历 查找 · 排序
数组封面
今日路线

三块内容:从声明到排序

01
数组入门
概念、声明、访问——索引从 0 开始。
02
初始化与易错
四种初始化、字符数组、越界陷阱。
03
遍历与例题
for/while/范围 for 遍历,统计、倒序、查找、冒泡排序。
01
PART 01 · 数组入门

一个名字,一排数据

认识数组:为什么需要它、怎么声明、怎么用下标访问。

概念 声明 下标访问
什么是数组

一个名字存多个同类型的值

数组的特点
✓ 存储相同类型的多个元素
✓ 元素在内存中连续存储
✓ 通过索引访问(从 0 开始)
✓ 大小声明时确定,运行期不能变
生活中的数组
一排储物柜,每个柜子有编号
停车场的车位,按编号排列
教室里的座位,按行列编号
?
想一想
要存 100 个学生的成绩,难道定义 100 个变量?数组就是干这个的。
数组的声明

数据类型 数组名[大小];

三个声明示例
int scores[5]; // 5 个整数 double prices[10]; // 10 个双精度浮点数 char letters[26]; // 26 个字符
int scores[5] → 连续内存,够放 5 个 int
▦
声明后系统分配连续的内存空间。
下标从 0 数起:scores[0] 是第一个。
数组元素的访问

下标从 0 开始:赋值与读取

int numbers[5]; numbers[0] = 10; // 第 1 个元素 numbers[1] = 20; // 第 2 个元素 numbers[2] = 30; numbers[3] = 40; numbers[4] = 50; // 第 5 个元素 cout << "第1个元素:" << numbers[0] << endl; cout << "第3个元素:" << numbers[2] << endl; cout << "最后一个元素:" << numbers[4] << endl;
运行结果
第1个元素:10
第3个元素:30
最后一个元素:50
!
重要
大小为 n 的数组,有效下标是 0 ~ n-1。越界访问是未定义行为,先检查下标。
02
PART 02 · 初始化

声明的同时就给值

四种初始化方式 + 字符数组的特殊玩法。

逐个指定 部分初始化 自动推导 字符数组
数组初始化

四种初始化方式

① 逐个指定
int scores[5] = {85, 92, 78, 96, 88};
② 部分初始化
int numbers[8] = {1, 2, 3}; // 后 5 个自动为 0
③ 自动推导大小
int values[] = {10, 20, 30, 40}; // 大小自动为 4
④ 全部初始化为 0
int zeros[6] = {0}; // 或 int zeros[6] = {};
0
没写满的部分 自动补 0——这是初始化最容易被利用的特性。
字符数组与 C 风格字符串

字符数组何时需要结束符?

char g1[6] = {'H','e','l','l','o','\0'}; char g2[] = "Hello"; // 自动添加 '\0' char name[20] = "Alice"; cout << g2 << endl; // 作为 C 字符串输出
!
C 风格字符串以零字符 '\0' 结尾,容量要把它算进去。std::string 是类类型,另有长度与存储管理。
char a[5] = {'A','l','i','c','e'}; for (int i=0; i<5; i++) cout << a[i]; // 上面逐元素输出安全,得到 Alice // cout << a; // 缺终止符,不能当 C 字符串 // char b[3] = "Alice"; // 编译错误:容量不足
!
字符数组本身不必带结束符;调用按 C 字符串读取的接口时才需要保证终止符存在。
初始化示例

各种初始化方式跑一遍

int scores[5] = {85, 92, 78, 96, 88}; int partial[6] = {1, 2, 3}; double prices[] = {12.5, 8.9, 15.6, 22.3}; cout << "成绩数组:"; for (int i=0; i<5; i++) cout << scores[i] << " "; cout << "\n部分初始化数组:"; for (int i=0; i<6; i++) cout << partial[i] << " "; cout << "\n价格数组大小:"; cout << sizeof(prices)/sizeof(prices[0]) << endl;
运行结果
成绩数组:85 92 78 96 88
部分初始化数组:1 2 3 0 0 0
价格数组大小:4
✎
动手练习:① 一周 7 天温度 ② 10 个学生姓名首字母 ③ 前 5 个偶数
03
PART 03 · 易错点

踩过的坑都在这

越界、大小误区、整体赋值、字符串结束符——五个高频错误。

越界访问 sizeof 误区 整体赋值 缺 '\0'
数组易错点

五个高频错误,逐项避开

#错误或条件正确做法
1访问 a[n]有效下标为 0~n−1
2混淆字节数与元素数同一作用域中:sizeof(a)/sizeof(a[0])
3声明后 arr = {…}声明时初始化,或逐个赋值
4把无终止符的字符数组当 C 字符串预留空间,并写入 '\0'
5拓展:普通数组形参中 sizeof(arr)通常已调整为指针类型;另传长度(函数单元详讲)
!
越界访问可能不报错,但行为未定义。数组大小和字符终止符都需要由程序保证。
04
PART 04 · 遍历

把每个元素都走过一遍

for、while、范围 for——三种遍历 + 统计操作。

for 遍历 while 遍历 范围 for 统计操作
for 遍历

i 从 0 到 size-1

int scores[5] = {85, 92, 78, 96, 88}; int size = sizeof(scores) / sizeof(scores[0]); cout << "所有成绩:" << endl; for (int i = 0; i < size; i++) { cout << "第" << (i+1) << "门课程:" << scores[i] << "分" << endl; }
运行结果
第1门课程:85分
第2门课程:92分
第3门课程:78分
第4门课程:96分
第5门课程:88分
i
数组下标和"第几个"差 1:第 i+1 个元素是 a[i]。
while 遍历

一周气温:while 也行

double temp[7] = {22.5, 24.8, 26.1, 23.7, 25.2, 27.4, 29.0}; int index = 0; while (index < 7) { cout << "第" << (index+1) << "天:" << temp[index] << "°C" << endl; index++; }
运行结果
第1天:22.5°C
第2天:24.8°C
…
第7天:29°C
↻
index 的初始化在循环外、更新在循环内——别忘了。
范围 for(C++11)

for (num : numbers) 更简洁

int numbers[] = {10, 20, 30, 40, 50}; cout << "修改前:"; for (int num : numbers) { // 只读遍历 cout << num << " "; } cout << endl; for (int& num : numbers) { // 引用 → 可修改 num *= 2; } cout << "修改后:"; for (int num : numbers) cout << num << " "; cout << endl;
修改前:10 20 30 40 50
修改后:20 40 60 80 100
&
只读用 int num;
要改元素用 int& num(引用)。
遍历中的常用操作

总分 · 平均 · 最大 · 最小

int scores[8] = {85,92,78,96,88,74,91,87}; int sum = 0; for (int i = 0; i < 8; i++) sum += scores[i]; double average = (double)sum / 8; int max_score = scores[0]; // 先假定第 0 个最大 int min_score = scores[0]; for (int i = 1; i < 8; i++) { if (scores[i] > max_score) max_score = scores[i]; if (scores[i] < min_score) min_score = scores[i]; } cout << "总分:" << sum << endl; cout << "平均分:" << average << endl; cout << "最高分:" << max_score << endl; cout << "最低分:" << min_score << endl;
运行结果
总分:691
平均分:86.375
最高分:96
最低分:74
±
找极值的套路:先假定第一个是极值,再逐个比较更新。
05
PART 05 · 例题实战

四道题把数组用熟

成绩统计、数组反转、元素查找、冒泡排序。

成绩统计 数组反转 元素查找 冒泡排序
例题 1 · 成绩统计系统

10 人的平均分与及格率

const int N = 10; double scores[N]; for (int i = 0; i < N; i++) cin >> scores[i]; // 先存起来 double sum = 0; for (int i = 0; i < N; i++) sum += scores[i]; int passed = 0; for (int i = 0; i < N; i++) if (scores[i] >= 60) passed++; cout << "平均分:" << sum / N << endl; cout << "及格人数:" << passed << "人" << endl; cout << "及格率:" << (double)passed / N * 100 << "%" << endl;
✎
先读入存进数组,再分三轮遍历:求和、数及格、算比例。
passed 是 int,算及格率要转 double。
例题 2 · 数组反转

首尾交换,转半圈就够

核心片段:已读入 numbers[0..size-1],0 ≤ size ≤ 1000。

for (int i = 0; i < size / 2; i++) { int temp = numbers[i]; numbers[i] = numbers[size - 1 - i]; numbers[size - 1 - i] = temp; }
1 2 3 4 5 6 7 8 9 10
→ 10 9 8 7 6 5 4 3 2 1
⇄
只需要循环 size / 2 次;
交换用 temp 暂存(三变量交换)。
例题 4 · 冒泡排序

相邻比较,大的往后冒

核心片段:已读入 numbers[0..size-1],0 ≤ size ≤ 1000。

for (int i = 0; i < size - 1; i++) { for (int j = 0; j < size - 1 - i; j++) { if (numbers[j] > numbers[j + 1]) { int temp = numbers[j]; numbers[j] = numbers[j + 1]; numbers[j + 1] = temp; } } }
64 34 25 12 22 11 90
→ 11 12 22 25 34 64 90
↕
外层 n-1 趟;内层每趟少比一个:size - 1 - i。
小结

今天你学会了:

数组基础
同类型 · 连续存储 下标从 0 开始 声明后大小固定
初始化与遍历
四种初始化 三循环接力遍历 '\0' 结尾
数组应用
统计 · 极值 查找带哨兵 冒泡排序
—

完整程序 · C++17