C++编程语言:从高效系统开发到现代编程范式的演进之路
目录
- 前言
- 一、c++简介
- 1.1 起源
- 1.2 c++的特点
- 二、开发环境搭建
- 2.1. 安装 Qt 开发工具
- 2.2 修改编码环境
- 2.3创建第一个 Qt 项目
- 2.4 c++的编译过程
- 2.5 代码示例
- 2.6 qt疑难杂症
- 2.6.1 遇到无法删除代码,一点击光标就变成小黑块
- 2.6.2 遇到运行不弹出终端
- 编辑
- 2.6.3 遇到终端有乱码
- 三、词法符号
- 3.1 关键字
- 3.1.1 ANSI C 32个关键字
- 3.1.2 C++ 补充的29个关键字
- 3.2 标识符
- 3.3 运算符
- 3.3.1 算术运算符
- 3.3.2 关系运算符
- 3.3.3 赋值运算符
- 3.3.4 逻辑运算符
- 3.3.5 位运算符
- 3.3.6运算符优先级(从高到低)
- 3.4 分隔符
- 3.5 标点符号
- 四、变量
- 4.1 格式
- 4.1.1 数据类型
- 4.2 变量赋值
- 4.3 局部变量与全局变量
- 4.4 内存分配
- 五、常量
- 5.1 整型常量
- 5.2 浮点常量
- 5.3 字符常量
- 5.4字符串常量
- 六、输入输出
- 6.1 基础准备
- 6.2 输出语句 cout
- 6.3 输入语句 cin
- 6.4 综合示例
- 6.5 注意事项
- 6.6 输入输出流程图示
- 七、控制语句
- 7.1 分支语句 - if/else
- 7.1.1 特性
- 7.1.2 完整示例:成绩分级
- 7.2. 分支语句 - switch/case
- 7.2.1. 格式
- 7.2.2. 特性
- 7.2.3 示例说明
- 7.3 循环语句-for
- 7.3.1 基本语法结构
- 7.3.2执行顺序
- 7.3.3 示例代码分析
- 7.3.4 关键特性
- 7.3.5 常见用法
- 7.3.6 练习:用for实现1-10求和
- 7.4 循环语句-while
- 7.4.1基本语法
- 7.4.2 示例
- 7.5 循环语句-do/while
- 7.5.1语法结构
- 执行顺序
- 7.5.2 与 while 循环的关键区别
- 7.5.3 示例代码分析
- 输出结果
- 7.6 练习题
- 七、数组
- 8.1 定义
- 8.2 特点
- 8.3 声明格式
- 8.4 初始化
- 8.5 字符数组
- 初始化方式:
- 关键区别:
- 8.6 练习:斐波那契数列逆序输出
- 九、指针
- 9.1 概念
- 9.2 定义格式
- 9.3 核心运算符
- 9.4 指针运算
- 9.4.1 赋值运算
- 9.4.2 算术运算
- 9.4.3 关系运算
- 9.5 练习
- 总结
前言
C++ 是一种通用的、高效的编程语言,由 Bjarne Stroustrup 于 1980 年代在贝尔实验室开发,最初作为 C 语言的扩展(最初称为“C with Classes”)。它结合了 低级内存操作(如 C 语言)和 高级抽象特性(如面向对象编程),广泛应用于系统开发、游戏引擎、嵌入式系统和高性能计算等领域。
一、c++简介
1.1 起源
C++ 的起源可以追溯到 20 世纪 80 年代初,由丹麦计算机科学家 Bjarne Stroustrup(本贾尼·斯特劳斯特卢普)在 贝尔实验室(Bell Labs)开发。其设计初衷是结合 C 语言的高效性与 面向对象编程(OOP) 的特性,同时解决当时其他语言在系统编程中的局限性。
-
C with Classes(1979–1983)
- Stroustrup 最初将新语言称为 “C with Classes”,目的是在保留 C 语言底层控制能力的同时,引入 类(class)、继承 和 多态 等面向对象特性。
- 他受到 Simula(面向对象鼻祖)和 ALGOL 等语言的影响,但认为这些语言在性能和灵活性上无法满足系统编程需求。
-
正式命名为 C++(1983)
- 1983 年,语言更名为 C++,名称中的
++
是 C 语言中的自增运算符,象征对 C 的改进和扩展。 - 新增特性包括 虚函数、运算符重载、引用 和 常量(
const
) 等。
- 1983 年,语言更名为 C++,名称中的
-
首个商业版本(1985)
- 1985 年,C++ 的第一个商业编译器 Cfront 发布,同时 Stroustrup 出版了经典著作《The C++ Programming Language》,成为语言的重要参考。
-
标准化进程(1998–至今)
- 1998 年:首个国际标准 ISO/IEC 14882:1998(C++98)发布,确立了语言的核心规范。
- C++11(2011):里程碑式更新,引入 自动类型推导(
auto
)、Lambda 表达式、右值引用 等现代特性。 - 后续版本:C++14、C++17、C++20 持续增强功能,如 模块化(Modules)、协程(Coroutines) 和 概念(Concepts)。
1.2 c++的特点
1. 多范式支持
- 面向对象编程(OOP):支持类、封装、继承、多态(包括虚函数和抽象类)等特性。
- 泛型编程:通过模板(Template)实现,支持类型无关的代码复用(如STL容器和算法)。
- 过程化编程:保留C语言的特性,支持函数和模块化设计。
2. 高性能与底层控制
- 直接内存操作:支持指针、手动内存管理,适合系统级开发。
- 编译型语言:代码直接编译为机器码,运行效率接近底层硬件。
- 资源敏感优化:支持内联汇编、寄存器变量等,适用于游戏引擎、高频交易等领域。
3. 标准模板库(STL)
- 丰富的数据结构与算法:如
vector
、map
、sort
等,提供高效实现。 - 迭代器模式:统一访问容器元素的接口,增强代码通用性。
- 函数对象与Lambda:支持函数式编程风格(C++11起)。
4. 内存管理
- RAII(资源获取即初始化):通过对象生命周期自动管理资源(如文件句柄、内存),避免泄漏。
- 智能指针:如
unique_ptr
、shared_ptr
(C++11引入),减少手动内存管理错误。
5. 现代语言特性(C++11及后续标准)
-
自动类型推导:
auto
关键字简化代码。 -
移动语义与右值引用:避免不必要的拷贝,提升性能(如
std::move
)。 -
Lambda表达式:支持匿名函数,便于编写回调和高阶函数。
-
并发支持:
std::thread
、原子操作等标准库工具。
6. 灵活性与复杂性
-
运算符重载:自定义类型支持运算符(如
+
、<<
),增强可读性。 -
多重继承与虚基类:允许复杂对象关系,但需谨慎使用。
-
模板元编程:编译时计算与类型推导,用于高性能库开发(如Boost)。
7. 兼容性与可移植性
-
与C语言兼容:可直接调用C库,复用现有代码。
-
跨平台支持:主流操作系统和硬件均有编译器(如GCC、Clang、MSVC)。
8. 静态类型系统
-
编译时类型检查:提前发现类型错误,增强安全性。
-
强类型约束:减少隐式类型转换的风险。
9. 异常处理
-
try/catch机制:支持错误处理,但部分场景推荐使用返回值或错误码。
10. 持续演进
-
标准更新:每三年发布新标准(如C++20引入模块、概念约束),逐步简化语法并增强功能。
二、开发环境搭建
2.1. 安装 Qt 开发工具
Windows 平台
-
下载 Qt 安装程序:
- 访问 Qt 官网
- 选择 "Download the Qt Online Installer"
-
运行安装程序:
- 选择组件(至少选择 Qt 版本和 Qt Creator)
- 推荐安装 MinGW 工具链(如果使用 MSVC 则需要安装 Visual Studio)
-
安装完成后,Qt Creator 将自动安装
2.2 修改编码环境
修改默认编码
2.3创建第一个 Qt 项目
- 选择 "文件" > "新建文件或项目"
- 设置项目名称和路径
- 选择构建套件
- 完成向导后,点击 "运行" 按钮编译并执行程序
2.4 c++的编译过程
C++是一种典型的编译型语言,其代码执行需要经过完整的编译和链接过程。首先,程序员编写的源代码(.cpp/.h文件)会被编译器(如GCC、Clang或MSVC)进行词法分析、语法分析和语义检查,通过后生成与平台相关的目标文件(.o或.obj文件),该文件包含机器码和符号表但尚未解决外部依赖。接着,链接器将多个目标文件与库文件进行整合,解析函数和变量的引用关系,完成地址重定位,最终生成可执行文件(如Windows的.exe或Linux的.out)
2.5 代码示例
// 引入输入输出流库,提供基本的输入输出功能
// iostream 包含标准输入输出对象如 cin, cout, cerr, clog 等
#include <iostream>// 使用标准命名空间 std
// 这样可以直接使用 std 中的成员(如 cout, endl)而无需前缀 std::
using namespace std;// 主函数,程序执行的入口点
// 每个C++程序必须有且仅有一个 main 函数
// int 表示该函数返回一个整数值
int main()
{// cout 是标准输出流对象,用于向控制台输出数据// << 是流插入运算符,用于将右侧的内容插入到左侧的流中// "Hello World!" 是要输出的字符串常量// endl 是特殊操作符,表示换行并刷新输出缓冲区// 这行代码会在控制台输出 "Hello World!" 并换行cout << "Hello World!" << endl;// return 语句结束 main 函数的执行// 返回 0 表示程序正常退出(非0值通常表示错误)// 在大多数操作系统中,0 表示成功,非0表示各种错误代码return 0;
}
2.6 qt疑难杂症
2.6.1 遇到无法删除代码,一点击光标就变成小黑块
千万不要选这个!!!
取消勾选!!!
2.6.2 遇到运行不弹出终端
改成启用
取消勾选!
2.6.3 遇到终端有乱码
辣鸡qt,该问题暂未解决,留待未来更新文章
三、词法符号
3.1 关键字
3.1.1 ANSI C 32个关键字
1. 存储类型
-
auto:自动变量(默认属性,通常省略)
-
extern:声明外部全局变量或函数
-
static:静态变量(作用域限制或持久化存储)
-
register:建议编译器将变量存储在寄存器中(现代编译器自动优化)
2. 数据类型
-
基本类型:
char
,int
,float
,double
-
修饰符:
-
长度:
short
,long
-
符号性:
signed
,unsigned
-
-
空类型:
void
(用于函数返回值、指针、参数占位)
3. 控制语句
-
条件分支:
if
,else
,switch
,case
,default
-
循环控制:
for
,while
,do
,break
,continue
-
跳转:
goto
,return
4. 构造数据类型
-
struct:结构体(组合不同类型的数据)
-
union:共用体(共享内存空间的不同数据类型)
-
enum:枚举(定义命名常量集合)
5. 其他关键字
-
const:常量(值不可修改)
-
sizeof:计算变量或类型的内存大小
-
typedef:为类型定义别名
-
volatile:禁止编译器优化(用于硬件寄存器等场景)
3.1.2 C++ 补充的29个关键字
1. 数据类型增强
-
bool:布尔类型(值为
true
/false
) -
wchar_t:宽字符类型(Unicode支持)
2. 面向对象
-
class:定义类
-
private/protected/public:访问权限控制
-
friend:友元(允许非成员访问私有成员)
-
virtual:虚函数(实现多态)
-
this:指向当前对象的指针
3. 动态内存管理
-
new:动态分配内存
-
delete:释放动态内存
4. 模板与泛型编程
-
template:定义模板
-
typename:声明模板中的类型参数
5. 异常处理
-
try:异常检测代码块
-
catch:捕获并处理异常
-
throw:抛出异常
6. 运算符与函数特性
-
operator:运算符重载
-
inline:内联函数(减少函数调用开销)
7. 命名空间与别名
-
namespace:定义命名空间(避免命名冲突)
-
using:引入命名空间或定义类型别名
8. 其他
-
mutable:允许在const成员函数中修改成员变量
-
explicit:禁止隐式类型转换(构造函数)
3.2 标识符
-
组成字符
标识符只能由字母(A-Z, a-z)、数字(0-9)和下划线(_)组成,不允许其他特殊字符(如$
、@
、空格等)。 -
首字符限制
第一个字符必须是字母或下划线,不能是数字。 -
关键字冲突
标识符不能与C语言的关键字(如int
、if
、return
等)或保留标识符(如_Bool
、_Alignas
等)相同。不同C标准(C89/C99/C11)的关键字可能不同,需注意兼容性。 -
区分大小写
C语言严格区分大小写,例如var
、Var
和VAR
是三个不同的标识符。 -
保留标识符
- 以双下划线(
__
)开头或单下划线后跟大写字母(如_A
)的标识符保留给编译器或标准库使用(如__LINE__
、_STDC__
)。 - 标准库函数名(如
printf
、malloc
)和类型名(如size_t
、FILE
)也应避免使用。
- 以双下划线(
3.3 运算符
3.3.1 算术运算符
运算符 | 名称 | 说明 |
---|---|---|
+ | 加法 | 数值相加或字符串拼接 |
- | 减法 | 数值相减 |
* | 乘法 | 数值相乘 |
/ | 除法 | 整数除法截断小数(非向下取整),浮点数除法保留小数。如:5/2=2,5.0/2=2.5 |
% | 取模 | 取余数(结果符号与被除数一致)。如:7%3=1,-7%3=-1 |
++ | 自增 | ++a (先自增后使用),a++ (先使用后自增) |
-- | 自减 | 同自增逻辑 |
3.3.2 关系运算符
运算符 | 名称 | 说明 |
---|---|---|
> | 大于 | 比较数值大小 |
>= | 大于等于 | |
< | 小于 | |
<= | 小于等于 | |
== | 等于 | 基本类型比较值,对象比较引用地址 |
!= | 不等于 |
3.3.3 赋值运算符
运算符 | 名称 | 说明 |
---|---|---|
= | 赋值 | 右侧值赋给左侧变量 |
+= | 加后赋值 | a += 5 等价于a = a + 5 |
-= | 减后赋值 | |
*= | 乘后赋值 | |
/= | 除后赋值 | |
%= | 取模后赋值 |
3.3.4 逻辑运算符
运算符 | 名称 | 说明 |
---|---|---|
&& | 逻辑与 | 短路特性:左假则跳过右操作 |
` | ` | |
! | 逻辑非 | 取反布尔值 |
& | 非短路与 | 两侧均执行 |
` | ` | 非短路或 |
3.3.5 位运算符
运算符 | 名称 | 说明 |
---|---|---|
& | 按位与 | 两操作数位同为1时结果为1 |
` | ` | 按位或 |
^ | 按位异或 | 两操作数位不同时结果为1 |
~ | 按位取反 | 单目运算符,0变1,1变0 |
<< | 左移 | 高位丢弃,低位补0(等价乘2) |
>> | 带符号右移 | 正数补0,负数补1(等价除2,向下取整) |
>>> | 无符号右移 | 高位补0(负数会变正) |
3.3.6运算符优先级(从高到低)
()
、[]
、.
++
、--
、!
、~
*
、/
、%
+
、-
<<
、>>
、>>>
>
、>=
、<
、<=
==
、!=
&
、^
、|
&&
、||
?:
(三元运算符)=
、+=
、-=
等赋值运算符
3.4 分隔符
空白字符包括:空格符(
)、制表符(\t
)、换行符(\n
)。
它们在代码中的作用是 分隔语法单元,但不同语言对空白符的敏感度不同。
空白字符类型 | 作用场景 | 示例 |
---|---|---|
空格符 | 分隔变量名、运算符、关键字等 | int a = 5; |
制表符 | 缩进代码块(Python强制要求) | Python中:if x:\n\tprint(x) |
换行符 | 表示语句结束或代码块分隔(如C/Java的分号) | JavaScript中自动分号插入规则 |
3.5 标点符号
1. 逗号 ,
-
变量声明分隔:
int a = 1, b = 2;
-
函数参数分隔:
void func(int x, float y);
-
表达式分隔(逗号运算符):
int c = (a++, b++);
(按顺序执行) -
初始化列表:
std::vector<int> v = {1, 2, 3};
2. 分号 ;
-
语句结束符:
int a;
、a = 10;
-
控制结构结束:
if (cond) { ... };
(注意:if
后的代码块不需要分号) -
类/结构体定义结束:
class MyClass {};
(必须加分号) -
do-while
循环结束:do { ... } while (cond);
3. 冒号 :
-
类继承:
class Derived : public Base {};
-
成员初始化列表:
MyClass() : m_value(0) {}
-
标签语句:
label: ... goto label;
-
三目运算符:
condition ? a : b
-
作用域限定符(C++11):
enum class Color : int { Red, Green };
4. 花括号 {}
-
代码块作用域:
if (cond) { ... }
-
类/结构体/枚举定义:
struct Point { int x; int y; };
-
初始化列表:
int arr[] = {1, 2, 3};
或std::vector<int> v{1, 2, 3};
-
Lambda 表达式(C++11):
auto f = []() { ... };
5. 圆括号 ()
-
函数调用/声明:
func();
、void func(int param);
-
表达式优先级:
int c = (a + b) * 2;
-
类型转换:
float f = (float)3.14;
(C 风格)或static_cast<float>(3.14);
-
条件/循环结构:
if (cond) { ... }
、while (cond) { ... }
6. 中括号 []
-
数组声明/访问:
int arr[5];
、arr[0] = 10;
-
Lambda 捕获列表(C++11):
[&]() { ... }
(捕获外部变量) -
下标运算符重载:
T& operator[](int index);
-
属性说明符(C++11):
[[nodiscard]] int func();
补充标点符号
7. 尖括号 <>
-
模板参数:
std::vector<int> v;
-
头文件包含:
#include <iostream>
8. 双冒号 ::
-
作用域解析:
std::cout
、MyClass::staticMethod()
-
全局命名空间:
::globalVar
9. 点 .
和箭头 ->
-
成员访问:
obj.member
、ptr->member
10. 双引号 ""
和单引号 ''
-
字符串字面量:
"Hello"
-
字符字面量:
'A'
11. 反斜杠 \
-
转义字符:
\n
(换行)、\"
(双引号)
12. 波浪号 ~
-
析构函数:
~MyClass() {}
13. 问号 ?
-
三目运算符:
condition ? true_expr : false_expr
四、变量
4.1 格式
[存储类型] 数据类型 变量名;
- 存储类型:决定变量的存储位置和生命周期(如
auto
,static
,register
,extern
) - 数据类型:决定变量占用的内存大小和值域范围
- 变量名:需符合标识符规则(字母/下划线开头,不含空格,区分大小写)
4.1.1 数据类型
类型名称 | 字节大小 | 值域范围 | 说明 |
---|---|---|---|
char | 1 | -128 ~ 127 | ASCII字符 |
unsigned char | 1 | 0 ~ 255 | |
short | 2 | -32,768 ~ 32,767 | |
unsigned short | 2 | 0 ~ 65,535 | |
int | 4 | -231 ~ 231-1 | 默认整数类型 |
unsigned int | 4 | 0 ~ 4,294,967,295 | |
long | 4/8 | -231 ~ 231-1 或 -263 ~ 263-1 | 依赖系统架构 |
unsigned long | 4/8 | 0 ~ 232-1 或 264-1 | |
float | 4 | 约6-7位有效数字 | 单精度浮点数 |
double | 8 | 约15-16位有效数字 | 双精度浮点数 |
bool | 1 | false (0)/true (1) | C++新增,需包含头文件 |
std::string | 24-40* | 动态字符串 | C++类类型,需#include <string> |
4.2 变量赋值
初始化方式:
- 传统赋值
int a = 100; char ch = 'A'; // 单引号表示字符
- 构造函数式
float ft(3.14f);
- C++11统一初始化
double dbl{3.1415926}; // 禁止窄化转换 std::string s{"Hello"};
4.3 局部变量与全局变量
特性 | 局部变量 | 全局变量 |
---|---|---|
定义位置 | 函数或代码块内部 | 所有函数外部 |
存储区域 | 栈区(自动分配/释放) | 全局区(程序启动到结束存在) |
作用域 | 当前代码块 | 整个程序 |
生命周期 | 代码块执行期间 | 程序运行期间 |
默认值 | 未初始化时为随机值 | 自动初始化为零 |
4.4 内存分配
-
栈区
- 自动管理,存放局部变量、函数参数。
- 大小有限(默认约1-8MB),快速分配。
-
堆区
- 手动管理(
new
/delete
),存放动态对象。
int* ptr = new int(100); // 分配堆内存 delete ptr; // 释放内存
- 手动管理(
-
全局/静态区
- 存放全局变量、静态变量(
static
)、常量。
- 存放全局变量、静态变量(
-
常量区
- 存放字符串常量和
const
常量。
- 存放字符串常量和
五、常量
5.1 整型常量
-
表示方式:
- 十进制:普通数字,如
123
、-45
。 - 八进制:以
0
开头,如0123
(十进制83)。 - 十六进制:以
0x
或0X
开头,如0x1A
(十进制26)。 - 二进制:以
0b
或0B
开头(C++14起支持),如0b1010
(十进制10)。
- 十进制:普通数字,如
-
类型与后缀:
- 默认类型为
int
,具体大小由编译器决定。 - 后缀:
u
或U
:无符号类型(如123U
为unsigned int
)。l
或L
:long
类型(如123L
)。ll
或LL
:long long
类型(如123LL
)。- 可组合使用,如
0x1AULL
(unsigned long long
)。
- 默认类型为
5.2 浮点常量
-
表示方式:
- 小数形式:必须包含小数点或指数部分,如
3.14
、0.5
、100.0
。 - 科学计数法:用
e
或E
表示指数,如1.2e3
(1200)、5E-2
(0.05)。
- 小数形式:必须包含小数点或指数部分,如
-
类型与后缀:
- 默认类型为
double
。 - 后缀:
f
或F
:float
类型,如3.14f
。l
或L
:long double
类型,如3.14L
。
- 默认类型为
5.3 字符常量
-
表示方式:
- 用单引号
''
包裹,如'A'
、'5'
、'#'
。 - 转义字符:用于特殊符号,常见转义序列:
\n
:换行,\t
:制表符,\\
:反斜杠。\'
:单引号,\"
:双引号,\0
:空字符。
- 用单引号
-
宽字符:
- 前缀
L
表示宽字符(wchar_t
类型),如L'中'
。
- 前缀
-
注意事项:
- 字符常量只能包含单个字符,多字符(如
'ab'
)可能导致编译器警告或未定义值。
- 字符常量只能包含单个字符,多字符(如
5.4字符串常量
-
表示方式:
- 用双引号
""
包裹,如"Hello"
、"C++"
。 - 隐式以
\0
(空字符)结尾,例如"a"
存储为'a'
和'\0'
。
- 用双引号
-
存储方式:
- C风格字符串:
const char[]
类型,如const char* str = "Hello";
。 - C++ string类:
std::string
类型,需包含<string>
头文件。
- C风格字符串:
-
特性:
- 拼接:相邻字符串自动连接,如
"Hello" " World"
等价于"Hello World"
。 - 原始字符串(C++11):用
R"(...)"
避免转义,如R"(Path: C:\Users\)"
。
- 拼接:相邻字符串自动连接,如
-
注意事项:
- 不可修改字符串字面量,如
char* s = "abc"; s[0] = 'x';
会导致未定义行为。 - 使用
char[]
初始化时可自动添加\0
,如char arr[] = "abc";
(长度为4)。
- 不可修改字符串字面量,如
#include <iostream> // 包含输入输出流库,用于使用cout和endl
using namespace std; // 使用标准命名空间,避免重复写std::int main() // 主函数,程序入口
{// 用char类型存储单个字符,使用单引号包裹char st = 'a'; // 声明并初始化一个字符变量st,值为'a'// 字符串可以用字符数组或string类型存储// 字符数组:需预留空间存放结尾的'\0'空字符char arr[5] = "abc"; // 声明大小为5的字符数组,初始化为"abc"(实际占用4个元素:a,b,c,\0)// 数组剩余位置自动填充为'\0'string str = "hello"; // 使用string类存储字符串,无需手动管理内存和大小cout << arr << endl; // 输出字符数组arr,遇到'\0'停止cout << str << endl; // 输出string字符串,自动处理内存和长度return 0; // 返回0表示程序正常退出
}
六、输入输出
6.1 基础准备
#include <iostream> // 必须包含的头文件
using namespace std; // 使用 std 命名空间(或显式写 std::cout)
6.2 输出语句 cout
- 作用:向标准输出设备(如屏幕)发送数据。
- 运算符:
<<
(插入运算符),可连续拼接多个数据。 - 换行控制:使用
endl
或"\n"
。
示例代码:
int age = 25;
cout << "Hello, World!" << endl; // 输出字符串后换行
cout << "Age: " << age << "\n"; // 拼接变量和字符串,用 \n 换行
6.3 输入语句 cin
- 作用:从标准输入设备(如键盘)读取数据。
- 运算符:
>>
(提取运算符),按顺序提取数据到变量。 - 特性:自动跳过空白符(空格、制表符、换行)。
示例代码:
int num;
double score;
cout << "Enter a number and a score: ";
cin >> num >> score; // 连续输入多个值,用空格分隔
6.4 综合示例
#include <iostream>
using namespace std;
int main() {string name;int age;cout << "Enter your name: ";cin >> name; // 输入字符串(遇到空格停止)cout << "Enter your age: ";cin >> age; // 输入整数cout << "Name: " << name << "\nAge: " << age << endl;return 0;
}
6.5 注意事项
- 命名空间:若未写
using namespace std;
,需显式使用std::cout
和std::cin
。 - 数据类型匹配:输入时必须确保变量类型与数据一致,否则会导致错误状态。
int x; cin >> x; // 若用户输入非数字,x 将保留随机值,cin 进入错误状态
- 读取含空格的字符串:
cin >> name
遇到空格会停止,需用getline
读取整行:string fullName; cout << "Enter full name: "; cin.ignore(); // 清除之前输入残留的换行符 getline(cin, fullName); // 读取整行(包括空格)
6.6 输入输出流程图示
键盘输入 -> [cin] >> 变量 // 提取数据到变量
变量 -> [cout] << 屏幕显示 // 插入数据到输出流
掌握 cin
和 cout
是 C++ 交互的基础,后续可结合格式控制(如 <iomanip>
中的 setw
、setprecision
)进行更复杂的操作。
七、控制语句
7.1 分支语句 - if/else
基本语法:
if (表达式) {语句块1;
} else {语句块2;
}
7.1.1 特性
-
if-else关系
if
可以单独存在,但else
必须对应一个if
。else
必须紧跟最近的未匹配的if
,中间不能插入其他代码。
-
代码块与作用域
- 若省略大括号
{}
,if/else
仅控制紧随其后的一条语句。
示例:
if (num > 0)cout << "正数"; // 仅此句属于if elsecout << "非正数"; // 仅此句属于else
- 若省略大括号
7.1.2 完整示例:成绩分级
练习:从终端输入一个学生的成绩,判断学生成绩并打印成绩级别(使用if语句)
【90 - 100】 A
【80 - 89】 B
【70 - 79】 C
【60 - 69】 D
< 60 sorry you lost
#include <iostream>
using namespace std;
int main() {int score;cout << "请输入成绩(0-100): ";cin >> score;// 输入验证if (score < 0 || score > 100) {cout << "错误:成绩超出有效范围!" << endl;return 1;}// 分级判断if (score >= 90) {cout << "A" << endl;} else if (score >= 80) {cout << "B" << endl;} else if (score >= 70) {cout << "C" << endl;} else if (score >= 60) {cout << "D" << endl;} else {cout << "Sorry, you lost." << endl;}return 0;
}
7.2. 分支语句 - switch/case
7.2.1. 格式
switch(表达式)
{case 常量1:语句块1;break;case 常量2:语句块2;break;// 更多 case...default:语句块n;break;
}
7.2.2. 特性
-
表达式类型限制
- 表达式必须为 整型(如
int
、char
)或 枚举类型,不能为浮点类型(如float
、double
)或字符串(如char*
、字符串字面量)。
- 表达式必须为 整型(如
-
case 标签规则
case
后的常量必须是 整型常量表达式,且值唯一,不可重复。- 不允许使用变量或运行时计算的表达式。
-
break 的作用
- 每个
case
后通常需添加break
,否则程序会继续执行下一个case
的语句块(称为 穿透效应)。 - 利用穿透效应可合并多个
case
执行同一逻辑,但需明确注释以避免误解。
- 每个
-
default 分支
default
分支可选,用于处理未匹配的所有情况。default
后的break
可省略(若位于末尾),但若其后有其他case
,需谨慎处理穿透问题。default
可置于任何位置,但通常放在末尾以提高可读性。
-
执行流程
- 从匹配的
case
处开始执行,直至遇到break
或switch
结束。 - 若无匹配
case
且存在default
,则执行default
分支。
- 从匹配的
7.2.3 示例说明
int x = 2;
switch(x) {case 1:printf("One");break;case 2:printf("Two"); // 匹配后输出 "Two"// 无 break,继续穿透至 case 3case 3:printf("Three"); // 输出 "Three"break;default:printf("Unknown");
}
// 最终输出 "TwoThree"
7.3 循环语句-for
7.3.1 基本语法结构
for(表达式1; 表达式2; 表达式3) {// 循环体
}
- 表达式1:初始化语句(通常用于定义循环变量,仅在循环开始时执行一次)。
- 表达式2:循环条件(布尔表达式,决定是否继续循环)。
- 表达式3:更新语句(通常用于修改循环变量,在每次循环体执行后执行)。
7.3.2执行顺序
- 初始化:执行表达式1(为循环变量赋初值)。
- 条件检查:判断表达式2是否为
true
:- 若为
true
,执行循环体。 - 若为
false
,退出循环。
- 若为
- 更新循环变量:执行表达式3。
- 重复步骤2和3,直到条件为
false
。
7.3.3 示例代码分析
#include <iostream>
using namespace std;int main() {for(int i = 0; i < 5; i++) {cout << i << endl;}return 0;
}
输出:
0
1
2
3
4
执行流程:
i
初始化为0
。- 检查
i < 5
(0 < 5
为true
),执行循环体输出0
。 - 执行
i++
,i
变为1
。 - 重复条件检查,直到
i = 5
时条件不满足,循环终止。
7.3.4 关键特性
-
变量作用域:
- 循环变量可在表达式1中直接定义(如
for(int i = 0; ...)
),此时i
的作用域仅限于循环体内。 - 若在外部定义(如
int i; for(i = 0; ...)
),变量可在循环外访问。
- 循环变量可在表达式1中直接定义(如
-
灵活的表达式:
- 表达式1、表达式3可以为空或包含多个语句(用逗号分隔):
for(int i = 0, j = 10; i < 5; i++, j--) {// 循环体 }
- 表达式1、表达式3可以为空或包含多个语句(用逗号分隔):
-
无限循环:
for(;;) {// 需要内部通过 break 退出 }
7.3.5 常见用法
-
遍历数组:
int arr[] = {1, 2, 3, 4, 5}; for(int i = 0; i < 5; i++) {cout << arr[i] << " "; } // 输出:1 2 3 4 5
-
反向循环:
for(int i = 4; i >= 0; i--) {cout << i << " "; } // 输出:4 3 2 1 0
-
嵌套循环:
for(int i = 0; i < 3; i++) {for(int j = 0; j < 3; j++) {cout << "(" << i << "," << j << ") ";} } // 输出:(0,0) (0,1) (0,2) (1,0) ... (2,2)
7.3.6 练习:用for实现1-10求和
#include <iostream>
using namespace std;int main() {int sum = 0; // 初始化累加器为0// for循环:i从1到10,每次递增1for (int i = 1; i <= 10; i++) {sum += i; // 将当前i的值累加到sum}cout << "1到10的和为:" << sum << endl; // 输出结果return 0;
}
前置递增 vs 后置递增:
i++
与++i
在循环中效果相同,但前置递增(++i
)性能略优(对非内置类型更明显)。
7.4 循环语句-while
7.4.1基本语法
while (表达式) {// 语句块
}
- 执行顺序:先判断表达式是否为
true
,若为真则执行循环体,重复此过程直到表达式为false
。 - 特点:若初始条件为
false
,循环体一次都不执行。
7.4.2 示例
int i = 0;
while (i < 10) {i++;if (i == 5) continue; // 跳过 i=5 的输出if (i == 8) break; // 当 i=8 时终止循环cout << i << " ";
}
// 输出:1 2 3 4 6 7
7.5 循环语句-do/while
7.5.1语法结构
do {语句块;
} while (表达式); // 注意:末尾必须有分号
执行顺序
- 先执行一次语句块,再判断表达式是否为真。
- 若表达式为
true
,继续循环;若为false
,退出循环。
7.5.2 与 while
循环的关键区别
特性 | while 循环 | do/while 循环 |
---|---|---|
执行顺序 | 先判断条件,再执行循环体 | 先执行循环体,再判断条件 |
最少执行次数 | 0 次(条件初始为 false 时) | 1 次(无论条件是否满足) |
7.5.3 示例代码分析
#include <iostream>
using namespace std;int main() {int i = 0;// while 循环(被注释的原始代码)// while (i < 5) {// cout << i << endl;// i++;// }// do/while 循环do {cout << i << endl;i++;} while (i < 5);return 0;
}
输出结果
两种循环均输出:
0
1
2
3
4
原因:
i
初始值为0
,满足i < 5
的条件。- 两种循环均执行 5 次,直到
i
递增到 5 时退出。
7.6 练习题
编写一个程序,该程序读取整数,直到输入0,输入终止后,程序
应该报告输入的偶数(不包括0)总个数,偶数的平均值,输入的奇数总个数以及
奇数的平均值。
#include <iostream> // 输入输出流库
#include <iomanip> // 输入输出格式控制库using namespace std; // 使用标准命名空间int main() {// 变量声明int num; // 存储用户输入的临时变量int evenCount = 0; // 偶数计数器int evenSum = 0; // 偶数和int oddCount = 0; // 奇数计数器int oddSum = 0; // 奇数和// 用户输入提示cout << "Enter integers (0 to stop):\n";// 持续读取输入直到遇到0或非整数输入while (cin >> num && num != 0) {if (num % 2 == 0) { // 判断是否为偶数evenCount++; // 偶数计数增加evenSum += num; // 累加偶数和} else { // 奇数情况oddCount++; // 奇数计数增加oddSum += num; // 累加奇数和}}// 计算平均值(处理除零情况)// 使用 static_cast 确保浮点数除法double evenAvg = evenCount > 0 ? static_cast<double>(evenSum) / evenCount : 0.0;double oddAvg = oddCount > 0 ? static_cast<double>(oddSum) / oddCount : 0.0;// 设置固定小数点格式,保留两位小数cout << fixed << setprecision(2);// 输出统计结果cout << "Even numbers: " << evenCount << ", average: " << evenAvg << endl;cout << "Odd numbers: " << oddCount << ", average: " << oddAvg << endl;return 0; // 程序正常退出
}
七、数组
8.1 定义
数组是具有相同数据类型且内存连续的若干个变量的集合,组成数组的变量称为元素。
8.2 特点
- 数据类型相同
- 内存空间连续
- 支持随机访问(通过下标直接访问)
8.3 声明格式
[存储类型] 数据类型 数组名[元素个数];
- 存储类型:
auto
(默认)、static
、extern
等 - 元素个数:必须是常量表达式(C89标准)
8.4 初始化
- 全部初始化:可省略元素个数
int arr[] = {1, 2, 3}; // 自动推断为 arr[3]
- 部分初始化:未初始化的元素自动补0
int arr[5] = {1, 2}; // [1, 2, 0, 0, 0]
- 未初始化:元素值为随机值(静态数组自动初始化为0)
8.5 字符数组
初始化方式:
- 逐个字符初始化(需手动添加结尾符)
char st[32] = {'a', 'b', 'c', '\0'}; // 显式添加结束符
- 字符串字面量初始化(自动补
\0
)char st[32] = "hello"; // 实际占用6字节(含\0) char buf[] = "world"; // 自动推断为 buf[6]
关键区别:
char s[] = {'a','b','c'};
→ 长度为3,无结束符char s[] = "abc";
→ 长度为4,包含\0
8.6 练习:斐波那契数列逆序输出
#include <iostream>
using namespace std;int main() {int arr[10] = {1, 1}; // 初始化前两项// 生成数列(从第3项开始)for (int i = 2; i < 10; i++) {arr[i] = arr[i-1] + arr[i-2];}// 逆序输出for (int i = 9; i >= 0; i--) {cout << arr[i] << " ";}return 0;
}
九、指针
9.1 概念
- 地址:内存最小存储单元是字节,每个存储单元都有唯一编号(地址)
- 指针变量:专门存储内存地址的变量(大小固定:32位系统4字节/64位系统8字节)
- 指针本质:地址值的代称,指针变量是地址的容器
9.2 定义格式
[存储类型] 数据类型 *变量名;
// 示例
int *p1; // 指向int类型的指针
char *p2; // 指向char类型的指针
double *p3 = nullptr; // 初始化为空指针
9.3 核心运算符
运算符 | 作用 | 示例 |
---|---|---|
& | 取变量地址 | &num → 获取num的地址 |
* | 解引用(访问地址内容) | *p → 获取指针指向的值 |
9.4 指针运算
9.4.1 赋值运算
int num = 10;
int *p = # // 指向变量
int arr[3] = {1,2,3};
p = arr; // 指向数组首地址
int *p2 = p; // 指针间赋值
9.4.2 算术运算
- 特点:以数据类型大小为步长
int arr[5] = {10,20,30,40,50};
int *p = arr;
p++; // 移动sizeof(int)字节 → 指向arr[1]
p += 2; // 指向arr[3]
int diff = p - arr; // 结果3(间隔元素个数)
9.4.3 关系运算
- 规则:比较内存地址高低(需指向同一连续内存区域)
int *p1 = &arr[0];
int *p2 = &arr[2];
cout << (p1 < p2); // 输出1(true)
9.5 练习
练习:使用指针实现将字符串转换成整数。
如:"234" -->234
#include <iostream>
using namespace std;int string_to_int(const char* str) {int result = 0;// 遍历字符串直到结束符while (*str != '\0') {// 将当前字符转换为数字并累加到结果中result = result * 10 + (*str - '0');str++; // 移动指针到下一个字符}return result;
}int main() {const char* str = "234";int num = string_to_int(str);cout << num << endl; // 输出: 234return 0;
}
总结
C++作为Bjarne Stroustrup在1980年代开发的通用高效编程语言,融合了C语言的底层控制能力和面向对象、泛型编程等高级特性,成为系统开发、游戏引擎和高性能计算领域的核心工具。其演进历程从“C with Classes”到C++11/20的现代化改进,持续引入自动类型推导、智能指针、协程等特性,平衡性能与开发效率。文章系统解析了C++的起源、多范式支持、内存管理机制、开发环境搭建(如Qt工具链)、语法结构(词法符号、控制语句)、数据存储(变量、数组、指针)及输入输出操作,同时探讨了其灵活性与复杂性的双重特征,为开发者提供了从基础到实践的全面指南。