第1章 计算机基础知识

1.1 计算机发展史

计算机的发展是人类科技史上的重要里程碑,其历程大致可分为以下几个关键阶段:

1.1.1 早期构想阶段(19世纪)

  • 查尔斯·巴贝奇
    • 英国数学家、发明家
    • 提出差分机分析机的构想
  • 分析机
    • 具备现代计算机五大基本部件:输入设备、输出设备、存储器、运算器、控制器
    • 被视为现代计算机的雏形

1.1.2 电子管时代(20世纪40年代)

  • ENIAC(1946年)
    • 全称:Electronic Numerical Integrator and Computer
    • 世界上第一台通用电子数字计算机
    • 发明人:约翰·莫奇利和约翰·埃克特(美国)
    • 特点:体积庞大(30吨)、使用1.8万个电子管、运算速度5000次/秒
    • 意义:开启了电子计算机时代
  • 中国第一台通用数字电子计算机
    • 103机(1958年)
    • 研制单位:中国科学院计算技术研究所

1.1.3 计算机各代特点对比表

代次 时间 主要元件 特点 代表机型
第一代 1946-1957 电子管 体积大、耗电多、速度慢 ENIAC、EDVAC
第二代 1958-1964 晶体管 体积减小、可靠性提高 IBM 1401
第三代 1965-1970 中小规模集成电路 体积更小、功耗降低 IBM System/360
第四代 1971至今 大规模/超大规模集成电路 微型化、智能化、网络化 个人计算机

1.1.4 中国超级计算机成就

计算机名称 特点 重要成就
神威·太湖之光 中国自主研制,使用国产处理器 2016-2017年多次在TOP500中排名第一
天河系列 中国自主研发的超级计算机系统 天河二号曾多次获得TOP500第一
曙光系列 中国高性能计算机代表 广泛应用于科学计算和工程领域

1.2 人工智能的历史

1.2.1 诞生期(1950s)

  • 1950年:图灵发表《计算机器与智能》,提出"图灵测试"
  • 1956年达特茅斯会议,正式确立"人工智能"学科名称
  • 早期成就:能够解决代数问题、证明几何定理

1.2.2 第一次AI寒冬(1960s-1970s)

  • 原因
    • 技术限制:计算机性能不足
    • 资金减少:未达到预期效果
    • 理论瓶颈:无法解决复杂问题

1.2.3 专家系统时代(1980s)

  • 专家系统
    • 模仿人类专家解决问题的系统
    • 应用领域:医疗诊断、金融分析
  • 第二次AI寒冬(1987-1993)
    • 成本高昂、维护困难
    • 应用范围有限

1.2.4 现代AI突破(21世纪)

  • 推动技术
    • 大数据
    • 云计算
    • 深度学习
  • 里程碑事件
    • 2012年:深度学习在ImageNet图像识别比赛中取得突破
    • 2016年AlphaGo击败李世石,引发全球关注
    • 2018年:GPT系列模型开始发展
  • 应用领域
    • 语音识别(Siri、小爱同学)
    • 图像识别(人脸识别、自动驾驶)
    • 自然语言处理(机器翻译、智能客服)

1.3 计算机领域的代表人物

1.3.1 代表人物对比表

人物 国籍 称号 主要贡献 相关荣誉/纪念
艾伦·图灵 英国 计算机科学之父
人工智能之父
1. 提出图灵机概念
2. 设计图灵测试
3. 二战期间破解德国密码
图灵奖(计算机界诺贝尔奖)
冯·诺依曼 匈牙利/美国 现代计算机之父 提出冯·诺依曼体系结构 (存储程序概念) 现代计算机基础架构
查尔斯·巴贝奇 英国 计算机先驱 设计差分机和分析机 分析机被视为计算机雏形
戈登·摩尔 美国 摩尔定律提出者 摩尔定律:集成电路晶体管数量每18-24个月翻倍 英特尔公司创始人之一
丹尼斯·里奇 C语言之父 1. 发明C语言
2. 开发Unix操作系统
影响深远,C语言至今广泛应用
姚期智 中国/美国 计算机科学家 计算理论、密码学贡献 首位华人图灵奖得主(2000年)
比尔·盖茨 美国 微软创始人 推动个人计算机软件发展 Windows操作系统
史蒂夫·乔布斯 苹果创始人 Macintosh、iPhone、iPad等创新产品 改变人机交互方式

1.3.2补充知识点:

  1. 图灵奖
    • 设立时间:1966年
    • 设立机构:美国计算机协会(ACM)
    • 别称:"计算机界诺贝尔奖"
    • 首位华人获奖者:姚期智(2000年)
  2. 冯·诺依曼体系结构五大部件
    • 运算器
    • 控制器
    • 存储器
    • 输入设备
    • 输出设备

1.4 计算机硬件系统

1.4.1 计算机系统的组成

graph LR
    subgraph "硬件系统"
        subgraph "主机"
            CPU[CPU<br>运算器+控制器]
            MEM[内存]
        end
        
        subgraph "外部设备"
            IN[输入设备]
            OUT[输出设备]
            STOR[外存储器]
        end
    end
    
    subgraph "软件系统"
        SYS[系统软件]
        APP[应用软件]
    end
    
    计算机系统[计算机系统] --> 硬件系统
    计算机系统 --> 软件系统
    
    %% 数据流向示意
    IN --> MEM
    MEM --> CPU
    CPU --> MEM
    MEM --> OUT
    MEM <--> STOR
    
    %% 样式
    style 计算机系统 fill:#f9f,stroke:#333,stroke-width:2px
    style 硬件系统 fill:#e6f2ff,stroke:#333
    style 软件系统 fill:#e6ffe6,stroke:#333

1.4.2 冯·诺依曼结构

计算机硬件系统由五大部分组成:

  1. 运算器:执行算术运算和逻辑运算
  2. 控制器:指挥控制中心,协调整个电脑有序工作
  3. 存储器:保存各类程序的数据信息
  4. 输入设备:外界向计算机传送信息的装置
  5. 输出设备:把计算机处理过的信息以人们认识的形式表示出来

1.4.3 中央处理器(CPU)

  • 作用:计算机的"大脑",负责运算和控制
  • 组成
    • 控制器:指挥控制中心
    • 运算器:执行算术和逻辑运算
    • 寄存器:临时存储数据,提高速度
  • 常见CPU品牌:Intel、AMD、国产龙芯

1.4.4 存储器

类型 特点 作用 常见形式 是否临时
内存 临时存储器,速度快 存放当前运行的程序和数据 RAM、ROM、Cache
外存 永久存储器,速度慢 长期保存数据和程序 硬盘、U盘、光盘

1.4.5 输入设备

  • 输入设备(向计算机传送信息):
    • 基本:键盘、鼠标
    • 图像:扫描仪、摄像头、手写板
    • 声音:麦克风
    • 专用:游戏手柄、条码扫描器、传感器

1.4.6 输出设备

  • 输出设备(计算机向外界输出信息):
    • 显示:显示器、投影仪
    • 打印:打印机、3D打印机
    • 声音:音箱、耳机
    • 其他:绘图仪

1.4.7 计算机主机

  • 组成:CPU + 内存储器
  • 外设:输入设备、输出设备、外存储器

1.4.8 数据存储单位

  • 最小单位:位(bit,简写为b),可以是0或1
  • 基本单位:字节(Byte,简写为B),1B = 8b
  • 换算关系:以1024为进率
单位 英文 简称 换算关系 示例
bit b 最小单位,0或1 1b
字节 Byte B 1B = 8b 字母"A"占1B
千字节 Kilobyte KB 1KB = 1024B 一页文字约3KB
兆字节 Megabyte MB 1MB = 1024KB 一首MP3约4MB
吉字节 Gigabyte GB 1GB = 1024MB 一部电影约1GB
太字节 Terabyte TB 1TB = 1024GB 大型数据库

1.5 计算机软件系统

1.5.1 软件系统分类

类型 作用 示例
系统软件 管理和控制计算机所有软、硬件资源 操作系统、语言处理程序、数据库管理系统
应用软件 满足用户特定需求 聊天软件、办公软件、游戏软件、教育软件

1.5.2 操作系统

  • 三大功能
    1. 硬件管理:CPU调度、内存分配、设备驱动
    2. 软件支持:为应用程序提供运行环境
    3. 用户接口:命令行、图形界面
  • 常见操作系统
    • PC系统:Windows、macOS、Linux、Unix
    • 移动系统:Android、iOS、HarmonyOS
    • 国产系统华为鸿蒙(HarmonyOS,2019年发布)、统信UOS

1.5.3 编程语言处理程序

  • 编译器:将高级语言转换为机器语言
  • 解释器:逐行翻译执行程序
  • 汇编器:将汇编语言转换为机器语言

1.6 计算机语言

1.6.1 编程语言发展历程

类型 时期 特点 缺点
机器语言 1940s 二进制代码,CPU直接执行 难记忆、难编写、难调试
汇编语言 1950s 使用助记符,需汇编器转换 依赖硬件、可移植性差
高级语言 1950s至今 接近自然语言,易学易用 需编译或解释

1.6.2 高级语言分类

  • 面向过程:C、Pascal、Fortran
  • 面向对象:C++、Java、Python、C#
  • 脚本语言:JavaScript、PHP、Python

1.6.3 高级语言的执行过程

源代码 → 编译器 → 目标代码 → 链接器 → 可执行文件 → CPU执行

关键点

  • 高级语言不能直接在CPU上执行
  • 必须经过编译解释
  • C++属于编译型语言

1.7 计算机的分类

1.7.1 按性能和规模分类

类型 特点 应用领域 示例
超级计算机 运算速度极快(每秒万亿次以上) 气象预报、核能研究、基因分析 神威·太湖之光、天河二号
大型计算机 高可靠性、支持多用户同时使用 银行、证券、大型企业数据中心 IBM Z系列
小型计算机 性能适中,价格较低 中小型企业、学校 IBM Power系列
微型计算机 个人使用,价格便宜 个人办公、学习、娱乐 台式机、笔记本电脑
嵌入式计算机 嵌入其他设备,功能专一 智能家居、汽车电子、医疗设备 单片机、工控机

1.7.2 按用途分类

  • 通用计算机:可处理多种任务,如个人电脑
  • 专用计算机:针对特定任务优化,如ATM机、收银机
  • 服务器:为网络中的其他计算机提供服务
  • 工作站:高性能计算机,用于专业领域(如CAD设计)

1.7.3 按外形分类

  • 台式计算机
  • 便携式计算机(笔记本电脑、平板电脑)
  • 手持设备(智能手机、PDA)

1.8 计算机的应用

应用领域 特点 实际案例
科学计算 处理复杂数学问题,要求高精度 天气预报、航天轨道计算、地震模拟
数据处理 处理大量数据,进行统计分析 学生成绩管理、银行账户管理、人口普查
过程控制 实时监控和调节生产过程 化工生产控制、机器人控制、智能家居
人工智能 模拟人类智能行为 语音助手、自动驾驶、智能推荐
计算机辅助 帮助人类完成设计制造任务 CAD(设计)、CAM(制造)、CAI(教学)
网络通信 实现远程信息交换和资源共享 电子邮件、视频会议、在线学习
多媒体应用 处理图像、音频、视频 电影特效、游戏开发、数字音乐
教育培训 辅助教学和技能培训 编程学习平台、虚拟实验室

1.8.2 现代计算机应用趋势

  • 物联网:万物互联,智能感知
  • 云计算:资源共享,按需服务
  • 大数据:海量数据,智能分析
  • 边缘计算:靠近数据源,实时处理

第2章 程序的输入和输出

2.1 输入输出概述

2.1.1 什么是输入输出

  • 输入:从外部设备(键盘、文件等)读取数据到程序中
  • 输出:将程序处理的结果显示到外部设备(显示器、文件等)
  • 交互:输入输出是程序与用户交互的主要方式

2.1.2学习目标

  • 掌握C++基本输入输出语句
  • 理解整型和浮点型数据的输入输出
  • 能够编写简单的输入输出程序
  • 解决常见输入输出问题

2.1.3 C++输入输出特点

特点 说明 优势
流式I/O 数据像水流一样传输 简单直观
类型安全 自动识别数据类型 减少错误
缓冲区 数据先进入缓冲区再处理 提高效率

2.2 C++语言的输入输出

C++语言提供了输入输出流(I/O流)机制,通过cincout对象实现输入输出,这种方法比C语言更简便、安全。

2.2.1 基本框架(必须掌握)

#include <iostream>      // 1. 包含输入输出头文件
using namespace std;     // 2. 使用标准命名空间

int main() {             // 3. 主函数开始
    // 程序代码
    return 0;            // 4. 程序结束
}

2.2.2 输出语句(cout)

基本格式:

cout << 输出项1 << 输出项2 << ... << 输出项n;

详细解析:

  1. cout:标准输出流对象(console output)
  2. <<:插入运算符,将数据"插入"到输出流
  3. 输出项:可以是常量、变量、表达式

输出示例对比:

代码 输出结果 说明
cout << 5; 5 输出整数
cout << 3.14; 3.14 输出浮点数
cout << 'A'; A 输出字符
cout << "Hello"; Hello 输出字符串
cout << 2+3; 5 输出表达式结果

示例:

int age = 12;
double height = 1.65;
cout << "年龄:" << age << "岁" << endl;
cout << "身高:" << height << "米" << endl;
cout << "年龄和身高的和:" << age + height << endl;

输出结果:

年龄:12岁
身高:1.65米
年龄和身高的和:13.65

2.2.3 输入语句(cin)

基本格式:

cin >> 变量1 >> 变量2 >> ... >> 变量n;

详细解析:

  1. cin:标准输入流对象(console input)
  2. >>:提取运算符,从输入流中"提取"数据
  3. 变量:接收输入值的容器

示例:

#include <iostream>
using namespace std;

int main() {
    int num1, num2;
    double score;
    
    // 连续输入三个值
    cin >> num1 >> num2 >> score;
    
    // 输出验证
    cout << "整数:" << num1 << " 和 " << num2 << endl;
    cout << "浮点数:" << score << endl;
    
    return 0;
}

运行示例:

输入:10 20 98.5
输出:整数:10 和 20
      浮点数:98.5

输入特点总结:

  1. 自动类型转换:根据变量类型转换输入数据
  2. 空格分隔:用空格、制表符、换行符分隔数据
  3. 顺序匹配:按顺序将输入值赋给变量

2.3 数据类型与格式控制

2.3.1 整型数据的输入输出

整型数据类型对比:

类型 字节数 取值范围 GESP使用频率
int 4 -2,147,483,648 ~ 2,147,483,647 ★★★★★
short 2 -32,768 ~ 32,767 ★☆☆☆☆
long 4/8 根据系统不同

示例:

#include <iostream>
using namespace std;

int main() {
    int a, b;
    
    // 输入两个整数
    cin >> a >> b;
    
    // 计算并输出
    int sum = a + b;
    int difference = a - b;
    int product = a * b;
    
    cout << a << " + " << b << " = " << sum << endl;
    cout << a << " - " << b << " = " << difference << endl;
    cout << a << " × " << b << " = " << product << endl;
    
    // 整数除法(重要!)
    cout << a << " ÷ " << b << " = " << a / b << endl;
    
    return 0;
}

整数除法特性:

int a = 7, b = 2;
int result1 = a / b;      // 结果为3(小数部分丢失)
double result2 = a / b;   // 结果为3.0(仍然丢失小数部分)
double result3 = (double)a / b;  // 结果为3.5(正确方法)

⚠️ GESP考试常见陷阱

int a = 5, b = 2;
double c = a / b;  // c的值是2.0,不是2.5!

2.3.2 浮点型数据的输入输出

浮点型数据类型对比:

类型 字节数 精度 推荐程度
float 4 6-7位有效数字 ★★☆☆☆
double 8 15-17位有效数字 ★★★★★

示例:

#include <iostream>
using namespace std;

int main() {
    double length, width;
    
    // 输入长方形的长和宽
    cin >> length >> width;
    
    // 计算面积
    double area = length * width;
    
    // 输出结果
    cout << "长方形面积:" << area << endl;
    
    // 浮点数输出特点
    double pi = 3.141592653589793;
    cout << "圆周率:" << pi << endl;  // 默认输出6位有效数字
    
    return 0;
}

浮点数输出特性:

代码 可能输出 说明
cout << 3.14159; 3.14159 正常输出
cout << 314159.0; 314159 省略末尾的.0
cout << 0.0000314159; 3.14159e-05 科学计数法

2.4 常见问题与注意事项

2.4.1 输入时的常见问题

  1. 输入顺序错误:

    // ❌ 错误示例:先计算后输入
    int a, b, sum;
    sum = a + b;  // 错误:a和b还没有值
    cin >> a >> b;
    
    // ✅ 正确示例:先输入后计算
    int a, b, sum;
    cin >> a >> b;  // 先获取输入
    sum = a + b;    // 再计算
    
  2. 变量未初始化:

    // ❌ 危险做法:未初始化变量
    int a, b;  // a和b的值不确定(可能是任意值)
    cin >> a;  // 如果输入失败,b的值不确定
    
    // ✅ 推荐做法:声明时初始化
    int a = 0, b = 0;  // 初始化为0
    cin >> a >> b;     // 安全输入
    
  3. 输入类型不匹配

    // ❌ 危险:输入浮点数到整型变量
    int age;
    cin >> age;  // 如果输入"12.5",只会读取12,.5留在缓冲区
    
    // ✅ 安全:根据需要选择合适的类型
    double age;  // 如果需要小数
    cin >> age;  // 可以输入12.5
    

2.4.2 输出时的常见问题

  1. 忘记换行:

    // ❌ 输出结果连在一起
    cout << "Hello";
    cout << "World";
    
    // ✅ 使用endl或\n换行
    cout << "Hello" << endl;
    cout << "World" << endl;
    
    // 或者
    cout << "Hello\n";
    cout << "World\n";
    
  2. 输出格式混乱:

    // ❌ 格式混乱,不易阅读
    cout << "结果是" << result;
    
    // ✅ 添加适当空格和标点
    cout << "结果是:" << result << endl;
    
    // 更好:清晰标注
    cout << "计算结果 = " << result << endl;
    

2.4.3 GESP考试特别注意事项

  1. 程序开头必须写

    #include <iostream>
    using namespace std;
    
  2. main函数必须返回0

    int main() {
        // 代码
        return 0;  // 不能省略
    }
    
  3. 变量使用前必须定义

    // 错误
    sum = a + b;  // a和b未定义
    int a, b;
    
    // 正确
    int a, b, sum;
    cin >> a >> b;
    sum = a + b;
    

2.5 知识要点总结

2.5.1 必记知识点

  1. 头文件: #include <iostream>
  2. 命名空间: using namespace std;
  3. 输出对象: cout,配合<<使用
  4. 输入对象: cin,配合>>使用
  5. 换行方式: endl\n

2.5.2 基本语法格式

// 单个输出
cout << "Hello, World!" << endl;

// 多个输出
cout << "a=" << a << ", b=" << b << endl;

// 单个输入
cin >> a;

// 多个输入
cin >> a >> b >> c;

// 混合使用
cout << "请输入两个数:";
cin >> x >> y;
cout << "和是:" << x + y << endl;

2.5.3 常用数据类型(GESP一级)

数据类型 用途 示例 输入 输出
int 整数 int age = 12; cin >> age; cout << age;
double 小数 double score = 98.5; cin >> score; cout << score;
char 字符 char grade = 'A'; cin >> grade; cout << grade;

2.5.4 编程黄金法则(考试必记)

  1. 先包含,后使用:先写#include,再写代码
  2. 先定义,后使用:先定义变量,再使用变量
  3. 先输入,后计算:先获取输入,再进行计算
  4. 先计算,后输出:先计算结果,再输出显示
  5. 有始有终main函数以return 0;结束

第3章 变量与数据类型

3.1 变量的定义与概念

变量是程序中用于存储数据的容器,在使用前必须先进行定义,明确其数据类型和名称。

3.1.1 变量的基本概念

  • 定义:变量是程序中用于存储数据的容器
  • 比喻:变量就像贴有标签的盒子
    • 盒子有名称(变量名)
    • 盒子有类型(数据类型)
    • 盒子可以放东西(数据值)
    • 盒子的东西可以更换(重新赋值)

3.1.2 C++中变量的定义

基本格式:

数据类型 变量名;

不同定义方式对比:

定义方式 语法 示例 特点
单独定义 数据类型 变量名; int age; 只定义,不赋值
定义并初始化 数据类型 变量名 = 值; int score = 100; 定义同时赋值
多个同类型变量 数据类型 变量1, 变量2, ...; int a, b, c; 一行定义多个

定义示例代码:

// 方式1:单独定义
int age;
double height;
char grade;

// 方式2:定义并初始化
int score = 95;
double pi = 3.14159;
char initial = 'A';

// 方式3:定义多个变量
int x = 1, y = 2, z = 3;
double a, b, c;

3.2 变量的命名规则

变量命名需要遵循一定的规则,以保证程序的可读性和正确性

3.2.1 命名规则

规则 说明 示例
组成字符 只能由字母、数字和下划线组成 name, _count, student1
首字符 必须以字母或下划线开头,不能以数字开头 age(正确), _count(正确), 123num(错误)
大小写 区分大小写 ageAge是两个不同的变量
关键字 不能使用C/C++关键字作为变量名 int, float, if, for等不能用作变量名
长度限制 虽然没有严格限制,但应保持合理长度 一般不超过32个字符
可读性 应尽量做到见名知意 age表示年龄,score表示分数

3.2.2 合法与非法变量名示例

合法的变量名:

int age;              // 表示年龄
float average_score;  // 表示平均分
int student_count;    // 表示学生数量
double _price;        // 以下划线开头
int num1, num2;       // 包含数字

非法的变量名:

int 123num;      // 错误:以数字开头
float int;       // 错误:使用了关键字int
double a+b;      // 错误:包含非法字符"+"
int my age;      // 错误:包含空格
char 变量;        // 错误:包含中文字符

3.2.3 命名风格建议

  1. 小驼峰命名法

    int studentAge;
    float averageScore;
    
  2. 下划线分隔法

    int student_age;
    float average_score;
    
  3. 常量使用全大写

    const double PI = 3.14159;
    const int MAX_SIZE = 100;
    

3.3 变量的赋值

赋值是给变量赋予具体的值,通过赋值运算符"="来实现。

3.3.1 基本赋值

格式:

变量名 = 表达式;

其中,表达式可以是:

  • 常量:直接给定的值
  • 变量:其他变量的值
  • 运算表达式:包含运算符的表达式

示例:

// 定义变量
int a;
float b;
char c;
// 赋值操作
a = 5;           // 将常量5赋值给变量a
int d = 10;
a = d;           // 将变量d的值赋值给变量a
a = d + 3;       // 将d+3的结果赋值给a
b = 3.14;        // 将浮点数赋值给变量b
c = 'A';         // 将字符赋值给变量c

3.3.2 复合赋值

为了简化运算,C++提供了复合赋值运算符

常见的复合赋值运算符:

运算符 名称 示例 等价形式 运算结果
+= 加后赋值 a += 5; a = a + 5; a增加5
-= 减后赋值 a -= 3; a = a - 3; a减少3
*= 乘后赋值 a *= 2; a = a * 2; a乘以2
/= 除后赋值 a /= 4; a = a / 4; a除以4
%= 取模后赋值 a %= 3; a = a % 3; a对3取余

示例:

int x = 10;

x += 5;   // 等价于 x = x + 5, x的值变为15
x -= 3;   // 等价于 x = x - 3, x的值变为12
x *= 2;   // 等价于 x = x * 2, x的值变为24
x /= 4;   // 等价于 x = x / 4, x的值变为6
x %= 2;   // 等价于 x = x % 2, x的值变为0

3.3.3 赋值表达式的值

  • 特点:赋值表达式本身也有值,值就是被赋的值
  • 应用:可以连续赋值
int a, b, c;
a = b = c = 10;  // 从右向左:c=10, b=c, a=b

// 等价于:
c = 10;
b = c;  // b = 10
a = b;  // a = 10

3.4 数据类型

数据类型决定了变量存储的数据的种类和范围

3.4.1 基本数据类型

类型 关键字 字节数 取值范围 GESP使用频率
整数 int 4 -2,147,483,648 ~ 2,147,483,647 ★★★★★
长整数 long long 8 -9.2×10¹⁸ ~ 9.2×10¹⁸ ★☆☆☆☆
单精度浮点 float 4 ±3.4×10^±38,6-7位精度 ★★☆☆☆
双精度浮点 double 8 ±1.7×10^±308,15-17位精度 ★★★★★
字符 char 1 -128 ~ 127 或 0 ~ 255 ★★★★☆
布尔 bool true(1) 或 false(0) ★★★☆☆

整数类型(整型):

类型 全称 典型大小 示例
short 短整型 2字节 short s = 100;
int 整型 4字节 int age = 15;
long 长整型 4或8字节 long distance = 1000000L;
long long 长长整型 8字节 long long big = 10000000000LL;

示例:

#include <iostream>
using namespace std;

int main() {
    short smallNumber = 100;          // 小整数
    int age = 15;                     // 一般整数
    long population = 7800000000L;    // 较大整数
    long long veryBig = 10000000000LL; // 非常大的整数
    
    cout << "short: " << smallNumber << endl;
    cout << "int: " << age << endl;
    cout << "long: " << population << endl;
    cout << "long long: " << veryBig << endl;
    
    return 0;
}

浮点类型(浮点型):

类型 精度 内存 示例 适用场景
float 6-7位有效数字 4字节 float price = 99.99f; 对精度要求不高,节省内存
double 15-17位有效数字 8字节 double pi = 3.1415926535; 一般计算,推荐使用

示例:

#include <iostream>
using namespace std;

int main() {
    // float类型需要加f后缀
    float weight = 65.5f;        // 单精度
    float temperature = 36.8f;
    
    // double类型(默认)
    double pi = 3.141592653589793;
    double distance = 384400.0;  // 地球到月球距离(公里)
    
    cout << "体重: " << weight << "kg" << endl;
    cout << "体温: " << temperature << "°C" << endl;
    cout << "圆周率: " << pi << endl;
    cout << "地月距离: " << distance << "公里" << endl;
    
    return 0;
}

字符类型:

特点 说明 示例
存储单个字符 使用单引号 char grade = 'A';
实际存储整数 存储ASCII码值 char a = 65;(等价于'A')
可以进行运算 字符可以加减 char next = 'A' + 1;(得到'B')
转义字符 特殊字符表示 char newline = '\n';

示例:

#include <iostream>
using namespace std;

int main() {
    char letter = 'A';
    char digit = '5';
    char symbol = '+';
    char newline = '\n';
    char tab = '\t';
    
    cout << "字母: " << letter << endl;
    cout << "数字字符: " << digit << endl;
    cout << "符号: " << symbol << endl;
    
    // 字符运算
    char nextLetter = letter + 1;  // 'A' + 1 = 'B'
    cout << "下一个字母: " << nextLetter << endl;
    
    // 查看ASCII码
    cout << "A的ASCII码: " << (int)letter << endl;
    cout << "B的ASCII码: " << (int)nextLetter << endl;
    
    return 0;
}

布尔类型:

特点 说明 示例
只有两个值 truefalse bool isReady = true;
实际存储 true为1,false为0 bool flag = false;
用于条件判断 if、while等语句 if (isReady) { ... }
可以输出 输出1或0 cout << isReady; 输出1

示例:

#include <iostream>
using namespace std;

int main() {
    bool isSunny = true;
    bool isRaining = false;
    bool hasHomework = true;
    
    cout << "天气晴朗: " << isSunny << endl;      // 输出1
    cout << "正在下雨: " << isRaining << endl;    // 输出0
    cout << "有作业: " << hasHomework << endl;    // 输出1
    
    // 布尔运算
    bool canPlay = isSunny && !isRaining;
    cout << "可以出去玩: " << canPlay << endl;    // 输出1
    
    // 直接输出true/false(C++中需要设置)
    cout << boolalpha;  // 设置以true/false形式输出
    cout << "天气晴朗: " << isSunny << endl;      // 输出true
    cout << "正在下雨: " << isRaining << endl;    // 输出false
    
    return 0;
}

3.4.2 数据类型的选择原则

  1. 整数的选择
    • 一般整数使用int
    • 很大的整数考虑longlong long
  2. 小数的选择
    • 一般小数使用double(精度更高)
    • 对内存要求严格时使用float
  3. 字符的选择
    • 单个字符使用char
    • 多个字符(字符串)使用string(后续章节介绍)
  4. 布尔值的选择
    • 逻辑判断结果使用bool

3.4.3 数据类型的内存表示

// 各种数据类型的内存占用示例
#include <iostream>
using namespace std;

int main() {
    cout << "int类型占用字节数:" << sizeof(int) << endl;       // 通常为4
    cout << "float类型占用字节数:" << sizeof(float) << endl;   // 通常为4
    cout << "double类型占用字节数:" << sizeof(double) << endl; // 通常为8
    cout << "char类型占用字节数:" << sizeof(char) << endl;     // 通常为1
    cout << "bool类型占用字节数:" << sizeof(bool) << endl;     // 通常为1
    return 0;
}

3.5 数据类型转换

3.5.1 隐式类型转换

当不同类型的数据进行运算时,编译器会自动进行类型转换。

转换规则:

转换方向 说明 示例
小→大 占字节少的转为占字节多的 short → int → long
整→浮 整数转为浮点数 int → float → double
低精度→高精度 精度低的转为精度高的 float → double

示例:

#include <iostream>
using namespace std;

int main() {
    int a = 10;
    double b = 3.14;
    
    // 隐式转换:int → double
    double result1 = a + b;  // a先转为double,再相加
    cout << "10 + 3.14 = " << result1 << endl;
    
    // 隐式转换:int → double
    double result2 = a / b;  // a先转为double,再相除
    cout << "10 / 3.14 = " << result2 << endl;
    
    return 0;
}

3.5.2 显式类型转换(强制类型转换)

使用类型转换运算符明确指定转换类型。

格式:

(目标类型)表达式

示例:

int a = 10;
int b = 3;
double result;

// 将整数转换为浮点数进行计算
result = (double)a / (double)b;  // 结果为3.33333...
// 将浮点数转换为整数(会丢失小数部分)
int c = (int)3.14;  // c的值为3

3.6 常量

常量是在程序运行过程中值不会改变的量

3.6.1 常量的定义

使用const关键字:

const 数据类型 常量名 = 值;

示例:

const double PI = 3.14159;      // 圆周率常量
const int DAYS_IN_WEEK = 7;     // 一周的天数
const char NEW_LINE = '\n';     // 换行符常量

3.6.2 常量的特点

  1. 值不可变:一旦定义,就不能再修改
  2. 必须初始化:定义时必须赋值
  3. 命名约定:通常使用全大写字母和下划线

3.7 常见错误与注意事项

3.7.1 常见错误

  1. 变量未初始化就使用

    int a;          // 未初始化
    cout << a;      // 错误:a的值不确定
    
  2. 类型不匹配的赋值

    int a = 3.14;   // 警告:小数部分被截断
    
  3. 使用错误的变量名

    int age = 15;
    cout << Age;    // 错误:应为age,区分大小写
    
  4. 变量名与关键字冲突

    int int = 10;   // 错误:int是关键字
    

3.7.2 良好编程习惯

  1. 定义时初始化

    int count = 0;      // 好习惯
    float total = 0.0;  // 好习惯
    
  2. 使用有意义的变量名

    int student_age;     // 明确表示学生年龄
    double exam_score;   // 明确表示考试成绩
    
  3. 一行只定义一个变量

    int width;     // 更清晰
    int height;
    
  4. 保持变量作用域最小

    • 只在需要的地方定义变量
    • 避免定义全局变量

3.8 知识要点总结

3.8.1 核心概念

概念 说明 关键点
变量 存储数据的容器 必须先定义后使用
数据类型 决定数据的种类和范围 选择合适的类型
变量名 标识变量的名称 遵循命名规则,见名知意
赋值 给变量赋予值 使用"="运算符

3.8.2 常用数据类型

数据类型 用途 示例
int 存储整数 int age = 15;
double 存储小数 double pi = 3.14;
char 存储单个字符 char grade = 'A';
bool 存储真假值 bool is_true = true;

3.8.3 赋值运算符

运算符 作用 示例
= 基本赋值 a = 5;
+= 加后赋值 a += 3; 等价于 a = a + 3;
-= 减后赋值 a -= 2; 等价于 a = a - 2;
*= 乘后赋值 a *= 4; 等价于 a = a * 4;
/= 除后赋值 a /= 2; 等价于 a = a / 2;

3.8.4 命名规则要点

  1. 字母、数字、下划线组成
  2. 不能以数字开头
  3. 区分大小写
  4. 不能使用关键字
  5. 见名知意

第4章 表达式

4.1 表达式的基本概念

表达式是由运算符、操作数和括号按照一定规则组成的式子,用于计算并返回一个值

4.1.1 表达式的组成

  1. 操作数:参与运算的数据,可以是:
    • 常量:直接给定的数值,如35.0
    • 变量:存储数据的容器,如abc
    • 函数调用:返回值的函数(后续章节介绍)
  2. 运算符:对操作数进行运算的符号,如+-*/
  3. 表达式的值:表达式经过运算后得到的结果

4.1.2 GESP考试常见表达式类型

类型 示例 结果 说明
算术表达式 5 + 3 * 2 11 先乘后加
关系表达式 5 > 3 && 2 < 4 true(1) 逻辑与
赋值表达式 a = b = 5 a=5, b=5 连续赋值
条件表达式 (a>b)?a:b 较大值 三目运算符

4.2 算术表达式

算术表达式是由算术运算符连接操作数形成的表达式,用于进行数值计算。

4.2.1 算术运算符

运算符 名称 作用 示例 结果
+ 加法 求两个操作数的和 5 + 3 8
- 减法 求两个操作数的差 5 - 3 2
* 乘法 求两个操作数的积 5 * 3 15
/ 除法 求两个操作数的商 5.0 / 3 约1.6667
% 取余 求两个整数相除的余数 5 % 3 2
++ 自增 操作数的值加1 a++++a a的值增加1
-- 自减 操作数的值减1 a----a a的值减少1

4.2.2 除法运算注意事项

除法运算需要特别注意整数除法浮点数除法的区别:

整数除法

当两个操作数都是整数时,结果为整数,小数部分被截断:

int a = 5, b = 3;
int result = a / b;  // 结果为1,不是1.6667

浮点数除法

至少有一个操作数为浮点数时,结果为浮点数:

double a = 5.0;
int b = 3;
double result = a / b;  // 结果为1.66667

强制类型转换

可以通过类型转换将整数转为浮点数进行除法:

int a = 5, b = 3;
double result = (double)a / b;  // 结果为1.66667

4.2.3 取余运算注意事项

  1. 操作数必须为整数

    int a = 5, b = 3;
    int remainder = a % b;  // 正确:结果为2
    double x = 5.5, y = 2.5;
    // double rem = x % y;  // 错误:%运算符不能用于浮点数
    
  2. 结果的符号与被除数相同

    int a = 5, b = 3;
    int r1 = a % b;    // 5 % 3 = 2
    
    int c = -5, d = 3;
    int r2 = c % d;    // -5 % 3 = -2
    
    int e = 5, f = -3;
    int r3 = e % f;    // 5 % (-3) = 2
    
    int g = -5, h = -3;
    int r4 = g % h;    // -5 % (-3) = -2
    

4.2.4 自增自减运算符

自增(++)和自减(--)运算符有前缀后缀两种形式:

表达式 等价代码 表达式的值 变量值变化
a = 5; b = a++; b = a; a = a+1; 5 a=6, b=5
a = 5; b = ++a; a = a+1; b = a; 6 a=6, b=6
a = 5; b = a--; b = a; a = a-1; 5 a=4, b=5
a = 5; b = --a; a = a-1; b = a; 4 a=4, b=4

示例:

// ❌ 不推荐:复杂表达式中使用自增自减
int a = 5;
int b = a++ + ++a;  // 结果依赖编译器,避免使用

// ✅ 推荐:单独使用
int c = 5;
c++;  // 或 ++c;
cout << c;  // 输出6

4.3 赋值表达式

赋值表达式是由赋值运算符连接操作数形成的表达式,用于将一个值赋给变量

4.3.1 基本赋值运算符

基本赋值运算符为=,格式:

变量 = 表达式;

**功能:**将右边表达式的值赋给左边的变量,整个表达式的值为赋值后变量的值。

示例:

int a;
a = 5 + 3;  // 将8赋给a,表达式的值为8
int b = a;  // 将a的值赋给b
int c = (a = 10);  // 先将10赋给a,再将a的值赋给c
// c的值为10,a的值也为10

4.3.2 复合赋值运算符

复合赋值运算符是基本赋值运算符与其他运算符的结合:

运算符 示例 等价形式 含义
+= a += 3 a = a + 3 加后赋值
-= a -= 3 a = a - 3 减后赋值
*= a *= 3 a = a × 3 乘后赋值
/= a /= 3 a = a ÷ 3 除后赋值
%= a %= 3 a = a % 3 取余后赋值

示例:

int a = 10;
a += 5;   // a = 10 + 5 = 15
a -= 3;   // a = 15 - 3 = 12
a *= 2;   // a = 12 × 2 = 24
a /= 4;   // a = 24 ÷ 4 = 6
a %= 2;   // a = 6 % 2 = 0

复合赋值的优点:

  1. 简洁:代码更紧凑
  2. 高效:某些情况下编译器可以优化
  3. 易读:当变量名很长时更方便

4.4 关系表达式

关系表达式是由关系运算符连接操作数形成的表达式,用于比较两个操作数的大小关系,结果为布尔值

4.4.1 关系运算符

运算符 名称 作用 示例 结果
> 大于 判断左边是否大于右边 5 > 3 true
< 小于 判断左边是否小于右边 5 < 3 false
>= 大于等于 判断左边是否大于等于右边 5 >= 5 true
<= 小于等于 判断左边是否小于等于右边 5 <= 3 false
== 等于 判断两个操作数是否相等 5 == 3
!= 不等于 判断两个操作数是否不相等 5 != 3 true

C++中的布尔值:

  • true:真(实际值为1)
  • false:假(实际值为0)

示例:

#include <iostream>
using namespace std;

int main() {
    int a = 10, b = 5;
    cout << (a > b) << endl;   // 输出:1 (true)
    cout << (a < b) << endl;   // 输出:0 (false)
    cout << (a >= 10) << endl; // 输出:1 (true)
    cout << (b <= 5) << endl;  // 输出:1 (true)
    cout << (a == b) << endl;  // 输出:0 (false)
    cout << (a != b) << endl;  // 输出:1 (true)
    // 布尔值可以直接用true/false表示
    bool is_greater = (a > b);  // is_greater的值为true
    return 0;
}

4.4.2 注意事项

  1. 优先级:关系运算符的优先级低于算术运算符,高于赋值运算符

    int a = 5, b = 3, c = 2;
    bool result = a + b > c * 2;  // 先算a+b和c*2,再比较
    // 等价于:(5+3) > (2×2) → 8 > 4 → true
    
  2. 区分===

    int a = 5, b = 3;
    bool r1 = (a == b);  // 比较:a是否等于b,结果为false
    int r2 = (a = b);    // 赋值:将b的值赋给a,整个表达式的值为3
    // 注意:r1是布尔值,r2是整数值
    
  3. 浮点数比较:浮点数有精度问题,不要直接用==比较

    double a = 0.1 + 0.2;  // a可能是0.30000000000000004
    double b = 0.3;        // b是0.3
    // 不推荐
    bool wrong = (a == b);  // 可能为false
    // 推荐:比较差值是否小于一个很小的数
    double epsilon = 0.000001;
    bool correct = (abs(a - b) < epsilon);  // 正确方法
    

4.5 逻辑表达式

逻辑表达式是由逻辑运算符连接操作数形成的表达式,用于进行逻辑判断,结果为布尔值。

4.5.1 逻辑运算符

运算符 名称 作用 示例 结果
&& 逻辑与 两边的表达式都为真时,结果为真 (5>3) && (2<4) 1/true
|| 逻辑或 两边的表达式至少有一个为真时,结果为真 (2>5) && (3<4)
! 逻辑非 对表达式的结果取反 !(5>3) 0/false

示例:

#include <iostream>
using namespace std;

int main() {
    int age = 15;
    int score = 85;
    // 逻辑与:两个条件都满足
    bool is_qualified = (age >= 12) && (score >= 60);
    cout << "是否合格:" << is_qualified << endl;  // 输出:1 (true)
    // 逻辑或:至少一个条件满足
    bool is_special = (age < 10) || (score >= 90);
    cout << "是否特殊:" << is_special << endl;    // 输出:0 (false)
    // 逻辑非:取反
    bool is_not_adult = !(age >= 18);
    cout << "是否未成年:" << is_not_adult << endl; // 输出:1 (true)
    return 0;
}

4.5.2 短路求值

C++中的逻辑运算符&&||具有短路求值特性:

  1. 对于&&:如果左边的表达式为假,右边的表达式不再求值,结果直接为假
  2. 对于||:如果左边的表达式为真,右边的表达式不再求值,结果直接为真

4.6 条件表达式(三目表达式)

条件表达式是一种三目运算符(? :)构成的表达式,用于根据条件选择不同的值。

4.6.1 基本格式

表达式1 ? 表达式2 : 表达式3

4.6.2 运算规则

  1. 计算表达式1的值
  2. 如果表达式1的值为真(非0),则整个表达式的值为表达式2的值
  3. 如果表达式1的值为假(0),则整个表达式的值为表达式3的值

示例:

#include <iostream>
using namespace std;

int main() {
    int a = 10, b = 5;  
    // 求最大值
    int max = (a > b) ? a : b;
    cout << "最大值:" << max << endl;  // 输出:10
    // 成绩等级
    int score = 85;
    char grade = (score >= 90) ? 'A' : 
                 (score >= 80) ? 'B' :
                 (score >= 70) ? 'C' :
                 (score >= 60) ? 'D' : 'E';
    cout << "成绩等级:" << grade << endl;  // 输出:B
    return 0;
}

4.6.3 条件表达式的优点

  1. 简洁:一行代码完成简单的条件判断
  2. 可以作为表达式使用:可以放在赋值语句的右边
  3. 类型灵活:表达式2和表达式3可以是不同类型,但需要能隐式转换

注意事项:

// ✅ 可以:类型相同或可转换
int x = (a > b) ? 5 : 10;
double y = (a > b) ? 5.0 : 10;

// ❌ 不建议:类型完全不同
// char* z = (a > b) ? "Yes" : 0;  // 不推荐

4.7 逗号表达式

逗号表达式是由逗号连接多个表达式形成的表达式。

4.7.1 基本格式

表达式1, 表达式2, ..., 表达式n

4.7.2 运算规则

  1. 从左到右依次执行
  2. 整个表达式的值是最后一个表达式的值
  3. 优先级最低

示例:

int a = 1, b = 2, c;
c = (a++, b++, a + b);  // 执行顺序:a++(a=2), b++(b=3), a+b=5
// 结果:a=2, b=3, c=5

4.7.3 使用建议

  1. 谨慎使用:逗号表达式可能降低代码可读性
  2. 适用场景
    • for循环的初始化或更新部分
    • 需要依次执行多个操作并获取最后一个操作的值
  3. 避免过度使用:如果逻辑复杂,最好拆分成多行

4.8 运算符的优先级和结合性

4.8.1 运算符优先级

运算符的优先级决定了表达式中运算的先后顺序,优先级高的运算符先进行运算

常见运算符的优先级(从高到低):

优先级 运算符 描述 结合性
1 () 括号 左到右
2 ++ -- ! 自增、自减、逻辑非 右到左
3 * / % 乘法、除法、取余 左到右
4 + - 加法、减法
5 < <= > >= 关系运算符
6 == != 等于、不等于
7 && 逻辑与
8 || 逻辑或
9 ? : 条件运算符 右到左
10 = += -= *= /= %= 赋值运算符
11 , 逗号运算符 左到右

4.8.2 结合性

当多个优先级相同的运算符同时出现时,运算顺序由结合性决定:

  1. 左结合:从左到右运算(大多数运算符)

    a + b - c  // 先算a+b,再减c
    a * b / c  // 先算a*b,再除以c
    
  2. 右结合:从右到左运算(赋值运算符、条件运算符)

    a = b = c  // 先算b=c,再算a=b
    x ? y : z ? a : b  // 先算z?a:b,再算x?y:结果
    

4.8.3 优先级示例

#include <iostream>
using namespace std;

int main() {
    int a = 5, b = 3, c = 2;
    // 示例1:算术运算符优先级高于关系运算符
    bool r1 = a + b > c * 2;  // 等价于:(5+3) > (2×2) → 8 > 4 → true
    // 示例2:关系运算符优先级高于逻辑运算符
    bool r2 = a > b && b > c;  // 等价于:(5>3) && (3>2) → true && true → true
    // 示例3:逻辑非优先级高于逻辑与
    bool r3 = !a && b;  // 等价于:(0) && 3 → false && true → false
    // 示例4:赋值运算符优先级最低
    int d;
    d = a + b * c;  // 先算b*c=6,再算a+6=11,最后赋值给d
    cout << "r1 = " << r1 << endl;  // 1
    cout << "r2 = " << r2 << endl;  // 1
    cout << "r3 = " << r3 << endl;  // 0
    cout << "d = " << d << endl;    // 11
    return 0;
}

4.8.4 使用建议

  1. 使用括号明确优先级

    // 不明确
    int result1 = a + b * c;
    
    // 明确
    int result2 = a + (b * c);  // 使用括号明确优先级
    int result3 = (a + b) * c;  // 如果意图是先加后乘
    
  2. 记忆口诀

    • 括号最高
    • 算术 > 关系 > 逻辑
    • 赋值最低
  3. 复杂表达式拆分

    // 复杂的表达式
    bool complex = (a > b) && (b > c) || (a == 5);
    
    // 拆分成多步更清晰
    bool cond1 = (a > b) && (b > c);
    bool cond2 = (a == 5);
    bool complex = cond1 || cond2;
    

4.9 常见错误与注意事项

4.9.1 常见错误

  1. 混淆===

    // ❌ 错误
    int a = 5;
    if (a = 10) {  // 总是真,因为a=10返回10(非0)
        cout << "a是10";
    }
    
    // ✅ 正确
    if (a == 10) {  // 比较
        cout << "a是10";
    }
    
  2. 整数除法问题

    int a = 5, b = 2;
    double result = a / b;  // 错误:结果为2.0,不是2.5
    
    // 正确
    double correct_result = (double)a / b;  // 2.5
    
  3. 自增自减混淆

    int a = 5;
    int b = a++ + ++a;  // 不推荐:结果依赖编译器
    
    // 推荐:拆分成多步
    int c = a++;
    int d = ++a;
    int e = c + d;
    

第5章 分支/判断结构

分支语句是程序控制流的重要组成部分,它允许程序根据不同的条件执行不同的代码块。在C/C++语言中,常见的分支语句包括 if 语句和 switch 语句。

5.1 if 语句

if 语句是最基本的分支语句,用于根据条件判断是否执行某段代码。

5.1.1 基本语法

if (条件表达式) {
    // 当条件表达式为真时执行的语句块
}
  • 条件表达式:可以是关系表达式逻辑表达式或其他返回布尔值的表达式(在C语言中,非0值表示真,0表示假;在C++中,true 表示真,false 表示假)。
  • 语句块:由一对大括号 {} 括起来的一条或多条语句。如果语句块中只有一条语句,大括号可以省略,但为了代码的可读性和规范性,建议始终使用大括号。

5.1.2 执行逻辑

首先计算条件表达式的值,如果值为真,则执行语句块中的内容;如果值为假,则跳过语句块,执行 if 语句之后的代码。

示例:

int age = 18;
if (age >= 18) {
    cout << "已成年" << endl;
}

上述代码中,条件表达式 age >= 18 的值为真,因此会输出“已成年”。


5.2 if-else 语句

if-else 语句在 if 语句的基础上增加了一个分支,用于在条件为假时执行另一段代码。

5.2.1 基本语法

if (条件表达式) {
    // 当条件表达式为真时执行的语句块
} else {
    // 当条件表达式为假时执行的语句块
}

5.2.2 执行逻辑

计算条件表达式的值,如果为真,执行 if 后面的语句块;如果为假,执行 else 后面的语句块。两个语句块只会执行其中一个。

示例:

int score = 75;
if (score >= 60) {
    printf("及格\n");
} else {
    printf("不及格\n");
}

这里条件表达式 score >= 60 为真,所以输出“及格”。若 score 为 50,条件为假,则输出“不及格”。


5.3 if-else if-else 语句

当需要判断多个条件时,可以使用 if-else if-else 语句,它可以实现多分支选择。

5.3.1 基本语法

if (条件表达式1) {
    // 条件表达式1为真时执行的语句块
} else if (条件表达式2) {
    // 条件表达式1为假,条件表达式2为真时执行的语句块
} else if (条件表达式3) {
    // 前面的条件都为假,条件表达式3为真时执行的语句块
} ... else {
    // 所有条件都为假时执行的语句块
}

5.3.2 执行逻辑

程序会依次判断各个条件表达式,当遇到第一个为真的条件表达式时,执行对应的语句块,然后跳过整个 if-else if-else 结构;如果所有条件表达式都为假,则执行 else 后面的语句块(如果有 else 的话)。

示例:

int grade = 85;
if (grade >= 90) {
    printf("优秀\n");
} else if (grade >= 80) {
    printf("良好\n");
} else if (grade >= 60) {
    printf("及格\n");
} else {
    printf("不及格\n");
}

上述代码中,grade 为 85,满足 grade >= 80,因此输出“良好”。

5.3.3 注意事项

  • 各个条件表达式的判断顺序很重要,应将范围小的条件放在前面,避免条件被覆盖。例如,若将 grade >= 60 放在 grade >= 80 前面,则 85 分会被判断为“及格”,而不是“良好”。
  • else 子句是可选的,如果没有 else,当所有条件都为假时,整个结构不执行任何操作。

5.4 switch 语句

switch 语句也用于多分支选择,适用于判断一个变量与多个常量值是否相等的情况。

5.4.1 基本语法

switch (表达式) {
    case 常量值1:
        // 当表达式的值等于常量值1时执行的语句
        break;
    case 常量值2:
        // 当表达式的值等于常量值2时执行的语句
        break;
    ...
    case 常量值n:
        // 当表达式的值等于常量值n时执行的语句
        break;
    default:
        // 当表达式的值不等于任何常量值时执行的语句
        break;
}
规则 说明 示例
表达式类型 必须是整型或字符型 int, char, 枚举
case常量 必须是常量,不能重复 case 1:, case 'A':
break作用 跳出switch,防止贯穿 通常每个case都要break
default 可选,处理未匹配情况 建议总是包含

5.4.2 执行逻辑

首先计算表达式的值,然后将该值与各个 case 后面的常量值进行比较。如果找到匹配的常量值,就从该 case 处开始执行语句,直到遇到 break 语句或 switch 语句结束;如果没有找到匹配的常量值,且有 default 子句,则执行 default 后面的语句。

示例:

char grade = 'B';
switch (grade) {
    case 'A':
        printf("优秀\n");
        break;
    case 'B':
        printf("良好\n");
        break;
    case 'C':
        printf("及格\n");
        break;
    default:
        printf("不及格\n");
        break;
}

由于 grade 的值为 'B',所以会执行 case 'B' 后面的语句,输出“良好”,然后遇到 break,跳出 switch 语句。

5.4.3 注意事项

  • switch 语句中的表达式和 case 后面的常量值必须是整数类型。

  • 多个 case 可以共享同一段执行语句,即省略中间的 break,例如:

    switch (num) {
        case 1:
        case 3:
        case 5:
            printf("奇数\n");
            break;
        case 2:
        case 4:
        case 6:
            printf("偶数\n");
            break;
    }
    

    num 为 1、3、5 时,都会输出“奇数”;为 2、4、6 时,输出“偶数”。

  • default 子句的位置可以灵活放置,不一定在最后,但通常建议放在最后。


5.5 分支语句的嵌套

分支语句可以嵌套使用,即在 if 语句或 switch 语句的语句块中包含其他分支语句。

示例:

int score;
char gender;
cin >> score >> gender;

if (score >= 60) {
    if (gender == 'M') {
        cout << "男生及格";
    } else if (gender == 'F') {
        cout << "女生及格";
    } else {
        cout << "性别输入错误";
    }
} else {
    cout << "不及格";
}

上述代码中,外层 if 语句判断 a 是否大于 b,若为真,内层 if 语句再判断 ab 大多少,实现了更复杂的条件判断。

嵌套时需注意代码的缩进,以提高可读性,同时要注意各层分支的匹配关系,避免逻辑混乱。

第6章 循环结构

循环语句是程序设计中用于重复执行某段代码的重要结构,它能让程序根据条件多次执行相同或相似的操作,极大地提高代码的效率和灵活性。在C/C++中,常见的循环语句包括 for循环while循环do-while循环。此外,还可以使用 breakcontinue 语句对循环流程进行控制。


6.1 for循环

for循环是一种结构清晰、使用灵活的循环语句,特别适用于已知循环次数的场景

6.1.1 基本语法

for (初始化表达式; 循环条件表达式; 循环后操作表达式) {
    // 循环体:需要重复执行的语句块
}
  • 初始化表达式:在循环开始前执行一次,通常用于初始化循环变量。
  • 循环条件表达式:每次执行循环体前判断,若为真则执行循环体,否则退出循环。
  • 循环后操作表达式:每次循环体执行完后执行,通常用于更新循环变量。
  • 循环体:需要重复执行的代码块,建议始终使用大括号 {}

6.1.2 执行流程

开始
  ↓
初始化 → 循环条件 → 假 → 结束
          ↓真
        循环体
          ↓
         更新
          ↓
      循环条件

6.1.3 示例

// 输出1到5的整数
for (int i = 1; i <= 5; i++) {
    cout << i << " ";
}
// 输出结果:1 2 3 4 5

6.1.4 特殊for循环形式

// 1. 省略初始化(已在前面定义)
int i = 0;
for (; i < 10; i++) { ... }

// 2. 省略更新(在循环体内更新)
for (int i = 0; i < 10;) {
    i++;  // 在循环体内更新
}

// 3. 无限循环(慎用!)
for (;;) {  // 相当于while(true)
    // 需要break退出
}

// 4. 多个变量
for (int i=0, j=10; i<j; i++, j--) {
    cout << i << " " << j << endl;
}

6.2 while循环

while循环是一种先判断条件再执行循环体的循环语句,适用于循环次数不确定但已知终止条件的场景。

6.2.1 基本语法

while (循环条件表达式) {
    // 循环体
}

6.2.2 while vs for 对比

特点 for循环 while循环
适用场景 循环次数已知 循环次数未知
初始化 在()内 在循环外
更新 在循环体内
可读性 结构紧凑 更灵活

6.2.3 示例

int score;
cout << "请输入成绩(0-100): ";
cin >> score;

while (score < 0 || score > 100) {
    cout << "输入错误,请重新输入: ";
    cin >> score;
}
cout << "输入正确: " << score;

6.2.4 注意事项

  • 必须在循环体内包含改变循环条件的语句,否则可能导致无限循环。
  • 初始化操作需在循环外完成,变量更新在循环体内实现。

6.3 do-while循环

do-while循环是一种先执行循环体再判断条件的循环语句,保证循环体至少执行一次,适用于需要先执行一次再判断是否继续的场景。

6.3.1 基本语法

do {
    // 循环体
} while (循环条件表达式);

注意:表达式末尾的分号不可省略。

6.3.2 执行流程

  1. 执行循环体。
  2. 判断循环条件表达式:
    • 若为真,返回步骤1;
    • 若为假,退出循环。

6.3.3 示例

// 输入一个正整数,直到输入正确为止
int num;
do {
    printf("请输入一个正整数:");
    scanf("%d", &num);
} while (num <= 0);
printf("你输入的正整数是:%d\n", num);

6.3.4 与while的区别

// while:先判断,后执行(可能一次都不执行)
int i = 10;
while (i < 5) {  // 条件为假
    cout << i;   // 不执行
}

// do-while:先执行,后判断(至少执行一次)
int j = 10;
do {
    cout << j;   // 执行一次,输出10
} while (j < 5); // 然后判断条件为假,退出

6.4 循环控制语句

循环控制语句用于在循环过程中改变循环的执行流程,包括 breakcontinue

6.4.1 break语句

用于立即终止当前循环,跳出循环体,执行循环后面的代码。

// 寻找1到10中第一个能被3整除的数
for (int i = 1; i <= 10; i++) {
    if (i % 3 == 0) {
        cout << "找到的数是:" << i << endl;
        break; // 找到后立即退出循环
    }
}
// 输出:找到的数是:3

6.4.2 continue语句

用于跳过本次循环中剩余的语句,直接进入下一次循环的判断。

// 输出1到10中的奇数
for (int i = 1; i <= 10; i++) {
    if (i % 2 == 0) {
        continue; // 跳过偶数
    }
    printf("%d ", i);
}
// 输出结果:1 3 5 7 9

6.4.3 break与continue的区别

  • break:完全终止循环,不再进行后续的循环判断和执行。
  • continue:仅跳过当前循环的剩余部分,继续下一次循环的判断和执行。

6.4.4 break vs continue 对比

操作 作用 示例
break 完全退出循环 找到目标后停止搜索
continue 跳过本次循环 跳过不符合条件的数据

6.5 循环嵌套

6.5.1 嵌套循环执行原理

for (int i = 1; i <= 3; i++) {      // 外层循环
    for (int j = 1; j <= 2; j++) {  // 内层循环
        cout << "i=" << i << ", j=" << j << endl;
    }
}

输出结果:

i=1, j=1
i=1, j=2
i=2, j=1
i=2, j=2
i=3, j=1
i=3, j=2

执行次数:外层3次 × 内层2次 = 6次

6.5.2 典型应用:乘法表

// 打印九九乘法表
for (int i = 1; i <= 9; i++) {          // 行
    for (int j = 1; j <= i; j++) {      // 列,j<=i打印下三角
        cout << j << "×" << i << "=" << i*j << "\t";
    }
    cout << endl;  // 换行
}

6.5.3 控制嵌套循环

// break只退出当前层循环
for (int i = 1; i <= 3; i++) {
    for (int j = 1; j <= 3; j++) {
        if (i * j > 4) {
            break;  // 只退出内层循环
        }
        cout << i*j << " ";
    }
    cout << endl;
}

6.6 循环算法题训练

6.6.1 求和问题

// 1. 求1+2+3+...+n的和
int n, sum = 0;
cin >> n;
for (int i = 1; i <= n; i++) {
    sum += i;
}
cout << "和为: " << sum << endl;

// 2. 求1-100中偶数的和
int evenSum = 0;
for (int i = 2; i <= 100; i += 2) {
    evenSum += i;
}
cout << "偶数和: " << evenSum << endl;

6.6.2 计数问题

// 统计1-100中能被3整除的数的个数
int count = 0;
for (int i = 1; i <= 100; i++) {
    if (i % 3 == 0) {
        count++;
    }
}
cout << "个数: " << count << endl;

6.6.3 找最值问题

// 输入n个数,找最大值
int n, maxNum;
cin >> n >> maxNum;  // 先读n,再读第一个数作为初始最大值

for (int i = 1; i < n; i++) {
    int num;
    cin >> num;
    if (num > maxNum) {
        maxNum = num;
    }
}
cout << "最大值: " << maxNum << endl;

6.6.4 图形打印

// 打印直角三角形
int rows;
cin >> rows;
for (int i = 1; i <= rows; i++) {
    for (int j = 1; j <= i; j++) {
        cout << "*";
    }
    cout << endl;
}

// 打印倒三角形
for (int i = rows; i >= 1; i--) {
    for (int j = 1; j <= i; j++) {
        cout << "*";
    }
    cout << endl;
}