本系列为C++的入门学习者服务,旨在于为此前无C++基础的学习者简单介绍关于C++语言基础的部分知识,如果已入门C++,则不需要阅读本系列。
2.1 算法与流程图(不展开讲)
2.2 C++中的语句
语句是C++程序的最基本单位,以分号结束。
注:头文件包含属于编译预处理,不是C++语句。
1 |
|
1. 声明语句
用来定义或声明变量和函数。
1 | int a, b; |
2. 表达式语句
完成计算和操作。
1 | c = a + b; |
3. 控制语句
用来完成对程序流程的控制。
如:if
语句、for
语句、while
语句等。
4. 函数调用语句
用来完成函数的调用。
1 | strcpy(a, b); |
5. 空语句
单独分号构成的语句。
意义:用在无内容可写,却需要语句来进行填充的位置。常见于循环语句,注意和分号区分。
6. 复合语句
由一对{}
构成,用来包括多个语句。
- 形式:
{语句1; 语句2;}
1 | if(i <= 100) //该段语句只是示例,无实际意义 |
- 意义:用在只需要一个语句,但单个语句无法满足需求。
- 注:在语法上复合语句认为是一条语句。
2.3 分支结构
1. if语句
(1) 单分支if语句
1 | if(表达式) |
解释:表达式一般为逻辑或关系表达式,如果结果为true
,则运行语句。而如果表达式是其他类型,则自动转换,非0
为true
,0
为false
。

(2) 双分支if语句
1 | if(表达式) |
解释:如果表达式结果为true
,则运行语句1
,反之运行语句2
。

例:闰年判断(4倍数一般是闰年,整百数必是400倍数才是闰年)
1 | int year; |
注:if语句的嵌套
if语句的分支语句可以是一个新的if语句,叫做if语句的嵌套。
借助if的嵌套可以实现多分支的判断功能。
A. 嵌套在else语句:阶梯式if语句
1 | if(表达式) |
解释:依次对各个表达式进行判断,如果有满足true
的则执行对应语句,并终止整个语句。
(注意和hoi4伪语言区分开)

B. 嵌套在if语句:在if分支语句中增加新的if语句(不推荐)
C++规定了
if
和else
的“就近配对”原则,即相距最近且还没有配对的一对if
和else
首先配对。1
2
3
4
5
6if(表达式1)
if(表达式2)
语句1;
else
语句2;
//else将与第二个if匹配。如果需要强行更改配对关系,则要将属于同一层的语句放在
{}
中。1
2
3
4
5
6
7
8if(表达式1)
{
if(表达式2)
语句1;
}
else
语句2;
//else将与第一个if匹配。
2. 条件运算符 ?:
三目运算符?:
可以简化if语句表达。
1 | 表达式1 ? 表达式2 : 表达式3; |
解释:判定表达式1
,若成立则执行表达式2
,不成立则执行表达式3
。
注:
- 条件运算符中后两个表达式的类型和第一个表达式完全无关。
- 条件运算符等级仅高于赋值(
15
)。 - 条件运算符是右结合性,自右向左结合。
- 例:
a ? b : c ? d : e
应该理解为a ? b : (c ? d : e)
- 例:
3. switch语句
1 | switch(整型表达式) |
解释:
计算
switch
后的整型表达式值。逐个匹配
case
后表达式的值,如果相等则执行对应的语句序列。如果语句后有
break
则终止整个switch
语句,否则继续执行后续语句序列且不再进行判断。若所有
case
都无法匹配则执行default
语句。
例:计算学生的成绩等级
1 | int score; |
注:
switch
语句只能对整数和字符类型使用。- 只能判断表达式是否相等,不能判定不等大于小于。
case
后的表达式只能是常量表达式。break
语句的使用请务必注意。
2.4 循环结构
1. while语句
1 | while(表达式) |
解释:如果满足表达式则反复执行循环体语句直到不满足表达式为止。

例:求解1~100的和
1 | const int n=100; //用常变量利于修改程序 |
解析:
代码结束后
i
的值为101
。sum=0
不能遗忘,否则会出现随机数。做题看结果通常看头尾。
若循环体中有多个语句一定要用
{}
。部分题目中会将循环修正条件放入循环入口条件中,即将循环体中的
i++
放入while(i++<=n)
中,但一般不推荐这样写。
2. do-while语句
1 | do 循环体语句 |
解释:先做一次循环体语句,若表达式满足则继续循环,直到表达式不满足终止循环;若表达式不满足则不执行循环。
注:do-while
语句与while
语句的区别
do-while
语句至少执行一次循环体后再判断循环条件是否满足。while
语句先判断条件,然后才执行循环体,可能一次都不执行。
例:求解1~100的和
1 | const int n=100;//用常变量利于修改程序 |
3. for语句
1 | for (表达式1; 表达式2; 表达式3) |
解释:先执行式1,然后判断式2,真则执行循环体,后执行式3,接着重复判断式2,直到2为假结束整个循环。
注:
- 相对于while,式1相当于初始条件;式2相当于维持条件;式3相当于修正条件。
- for语句中只有式2是判定条件。
- for语句中三个表达式都可以为空,但是分号**
;
**一定要有。 - 省去1可以将初始条件放在
for
之前,省去3可以将修正条件放在循环体中,而省去2则表达式2的值将默认为true
,必须用其他方法结束循环。
例:求解1~100的和
1 | const int n=100; //用常变量利于修改程序 |
4. 三种循环的选择与注意
A.三种循环语句没有本质区别,可以互相代替。
B.当循环起点和终点值直接确定,推荐使用for
语句。
C.若终止条件不明确(如等待某值输入),推荐while
语句。
D.do-while
语句最典型场合是必须至少执行一次的循环。如展示菜单。
E.若循环外还要用某变量,则该变量不能在for()
和while()
语句中定义。
5. 循环语句的嵌套
当循环语句中的循环体中又有循环语句时,就构成了嵌套循环。
理解:以时钟的时针和分针为例:
时针每移动一格(大循环),分针就必须跑完一圈(小循环)。
解释:大循环每进行一次,小循环就完整循环一次。
注:大小循环的运行可能相关也可能不相关。
经典案例:打印问题
- 主要思想:利用循环算法,打印各种有规律的数字或图形。
- 基本思路:行是大循环,列是小循环。首先断定打印的行数,然后在每一行当中确定打印的列数以及每一列的空格和内容。行数、列数以及打印内容往往存在关联,需要分析清楚并用来控制循环的次数。
算法示例:

1 | for (int i = 1; i <= 4;++i) |
解析:
首先确定行数为4行。
每行包括前面空格后面*号。
空格数量和行号相等。
*号的数量是固定为7个。
打印完每一行之后要换行。
6. 循环中的控制语句
(1) break语句
- 在循环语句中遇到
break
,整个循环结束。 - 如果有多层循环嵌套,则
break
只结束最近的循环。
例:素数判断
基本思路:i
从2
到根号n
之间进行循环,将每个i
用n
去除,如果可以整除则直接判断不是素数;如果i
的整个循环走完仍不能整除才能判断n
是素数。
1 | int n, k, i; |
(2) continue语句
在循环语句中遇到continue
,当轮循环停止,立即开始下一轮循环。
例:输出100
以内的偶数。
1 | for (i = 1; i <= 100; i++) |
注:break
与continue
的区别:
break
终止整个循环,而continue
只是终止一次循环。
2.5 C++常用基本算法
1. 穷举法
- 主要思想:列出问题的所有可能性,按所需条件进行逐一筛选。
- 要求:在设计算法时,应尽可能减少循环的次数以提高效率。
(1) 素数问题
(2) 水仙花数问题
问题说明:如果一个三位数等于其各位数字的立方和,则该数为水仙花数。
问题思路:将所有的三位数用条件进行验证即可
代码:
1 | int i, a, b, c; //a,b,c分别为百位、十位、个位 |
(3) 完全数问题
问题说明:如果一个数等于其所有因子(自身除外)的和,则该数为完全数。
如:6=1+2+3
,28=1+2+4+7+14
问题思路:遍历一个数的所有因子,并将其求和之后判断与自己是否相等即可。
问题要点:如何遍历一个数的所有因子?
A.单个数的判断:
1 | int i, n, s=0; //注意s必须初始化为0 |
B.遍历指定区间的完全数:(以1000
以内为例)
- 未优化代码:正确但运算次数大,判断需要进行
n/2
次循环。
1 | int i, n, s; |
- 代码优化:当区间过大的时候,将其从
2
到根号n
进行循环,每次求和的时候同时加上成对因子,但如果有重复的因子需去除。
1 | int i, n, k, s=1; //因子必定有1,将s初始化为1减少一次循环 |
(4) 简单推理问题
例:某同学做了好事但不留名。校长问了4个人:A说不是我,B说是C,C说是D,D说C胡说。已知4人中有3人说的是真话,请问做好事的是谁?
问题思路:遍历所有可能做好事的人,统计说真话的人是否为3个即可。
问题要点:如何用程序来计算和统计本问题的真假?
1 | char man; |
2. 递推法
- 主要思想:按照某种规律,对同一个变量不断更改其值(递推),从而求解问题。
- 基本思路:确定递推项 → 确定递推起点 → 分析递推规律 → 判断终止条件
(1) 斐波那契数列
数列背景︰
数列
1,1,2,3,5,8…
为以意大利数学家费波纳切命名的数列。
定义小兔子t
时间后长为大兔子,大兔子会繁殖且繁殖周期为t
。
则1对小
兔子t
时间后长大为1对大
兔子。t
时间后变成2对(1对小1对大)。t
时间后变成3对(2对大1对小)。t
时间后变为5对(3对大2对小)等等。
问题背景:现用循环求出该数列的前n
项。
问题思路:不可能定义n
个变量逐个保存,只能用少数的变量反复使用来达到该效果。
问题要点:如何找出递推的变化规律?务必通过该问题,掌握递推算法的核心思想。
斐波那契数列递推思路:
确定递推项:三项
f1
,f2
,f3
递推起点:
f1=f2=1
递推规律:
f3=f1+f2
,然后旧f2
推出新f1
,旧f3
推出新f2
,再重复前述过程例:(右上到左下替换)
f1 f2 f3 1 1 2 1 2 3 2 3 5 终止条件:指定次数(本例为
n-2
次)
解法一:
1 | int f1=1, f2=1, f3, i; //只定义3个变量 |
解法二:
递推规律:新f1=旧f1+旧f2
;新f2=新f1+旧f2
旧 f1 | 旧 f2 | 新 f1 | 新 f2 |
---|---|---|---|
1 | 1 | 2 | 3 |
1 | int f1=1, f2=1, i; |
(2) sin(x)的求解问题
已知 sin(x) = x - x3 / 3! + x5 / 5! - x7 / 7! + …..
利用该公式求解sin(x)
的值,精度为10-6。
问题思路:观察每一项的分子、分母和符号位的值。当前项的符号位乘 -1
就是下一项的符号位;当前项的分子乘 x2 就是下一项的分子;当前项的分母乘以(2*n+1)*(2*n)
,即为下一项的分母,n
为当前的项数。
精度为10-6可用来控制循环的终止,如果计算的通项绝对值小于该值,则循环终止。
示例:求 sin 3 = ?
1 | double x = 3, s = 0, t = x; |
(3) 二分法求解方程问题
问题说明:假设f(x)
在区间[a,b]
中单调递增,且肯定有根,求解该根的值。
问题思路:取区间的一半判断其函数值,如果为负,则收缩区间为中点到右区间,反之为左区间到中点。重复上述过程,直到中点值为0
或满足精度要求即可。
问题要点:反复递推区间的左右值即可,当求出的中点值小于某区间即可终止。
示例:二分法求x2-2=0
1 | double a=0,b=2,c=(a+b)/2; //递推起点 |
(4) 整数分解问题
问题说明:输入任意正整数,判断其位数、计算各位数字之和、求解其倒序数、判断是否为回文数等问题。
问题思路:从个位数开始依次提取,其方法是对10
求余,然后将该数除以10
,并重复上述步骤,直到该数为0
则结束。
问题要点:上述思路仅限分解,如果是组装则逆向进行。
示例:求解12345的倒序数。
1 | int n = 12345,m = 0; |
3. 模拟法
基本思想:根据题目给出的规则,对题目要求的相关过程进行模拟。模拟法对于步骤比较繁杂的问题比较合适。
报数问题
题目:小张按1~20
报数,小李按1~30
报数,若两人同时开始,并以同样速度报数,当两人都报了1000
个数时,报相同数字的次数有多少?
思路:进行1000
次循环,每一次小张和小李各报一次数(注意调整下一次的值),统计相等次数即可。
1 | int round, zhang = 0, wang = 0, count = 0; |