Initial commit: C++ courseware

This commit is contained in:
xiaolinquan committed 2026-11-05 22:51:02 +08:00
commit 4a4ee7c287
1789 files changed
+373489

No files matched your search

@@ -0,0 +1,82 @@
# C++ 输入 (`cin`) 讲义
## 一、 程序只能算固定数据吗?
我们之前写的代码,所有的数字都是直接写在程序里的,比如 `int a = 5; int b = 3;`。这种写法把**数据写死**了。
大家思考一下,如果用户明天想算 `100 + 200` 怎么办?难道每次都要让程序员打开代码,改完数字再重新算一次吗?这显然是不现实的!
一个真正有价值的程序,应该是**智能的**——它能够随时接收用户提供的新数据,并自动计算出结果。今天,我们就要学习如何让程序接收用户提供的数据。
## 二、 认识 `cin`:控制台的数据接收员
为了让程序接收用户的键盘输入,C++ 提供了一个强大的工具:**`cin`**。
* **含义**:**`cin`** 是 Console Input(控制台输入)的缩写, c 对应着 Console, in 对应着 input。
* **作用**:**让用户在黑框框里==用键盘==输入数据**,然后程序会自动把这个数据==存入==我们提前准备好的==变量==中。
* **`cin` 使用 >> 运算符跟上准备好的变量来接收用户输入**。
### 1. `cin` 的运作过程
我们来看看 `cin` 是如何与我们之前学习的变量配合的:
```cpp
int num;
cin >> num;
cout << num;
```
1. **`int num;`** $\rightarrow$ 程序向内存申请了一个整数类型的空柜子,并在外面贴上名字标签 `num`。
2. **`cin >> num;`** $\rightarrow$ 程序==暂停运行==,等待用户操作。用户在键盘上敲下数字 `7` 并按下回车。**`>>`(称为提取符)**就像传送带一样,把键盘上的 `7` 抓过来,放进了名为 `num` 的抽屉里。
3. **`cout << num;`** $\rightarrow$ 获取名为 `num` 抽屉里的数据,并将其展示在屏幕上(输出 7)。
### 2. 语法与规则
输入单个数据:
**==语法格式==:** `cin >> 变量名;`
如果你想一次性让用户输入多个数据,那就需要准备多个变量,然后把传送带连起来用:
**==语法格式==:** `cin >> 变量名 >> 变量名 >> 变量名;` (可以通过 `>> 变量名` 的格式继续扩展)
```cpp
int a, b, c;
cin >> a; // 接收用户输入的一个整数到变量 a 中
cin >> b >> c; // 依次接收用户输入的两个整数到变量 b, c 中
```
> **输入规则:**
> 当使用 `cin >> a >> b;` 时,用户在黑框框里输入数据,**必须使用“空格”或者“回车”来隔开两个数字**(比如输入 `5 10`)。`cin` 它只要一遇到空格或回车,就知道第一个数据输入结束了,准备把下一个数据放进第二个抽屉里。
---
## 三、 解决题目中要求有输入的题目
现在我们拥有了所有的基础工具(变量、加减乘除、输入、输出)。接下来,我们要做一道完整的带有输入程序题。务必要记住:
==**"输入 -> 处理 -> 输出" 是完成程序题目的三个基本步骤。**==
**题目描述:请你实现输入两个整数,输出这两个整数的差。**
*(样例输入:2 3 $\rightarrow$ 样例输出:-1;样例输入:10 2 $\rightarrow$ 样例输出:8)*
**分析思路**:
1. **提取有效信息**:题目需要什么?(**==输入两个数==** $\rightarrow$ 相减 $\rightarrow$ 输出结果)。
2. **整理思路**:
* 准备两个变量(空抽屉)装输入的数。
* 用 `cin` 把用户敲的字放进抽屉。
* 处理数据:拿出来相减,结果放进第三个抽屉。
* 用 `cout` 展示第三个抽屉。
3. **将思路一步步翻译为C++ 代码**:
```cpp
int num1, num2; // 准备抽屉
cin >> num1 >> num2; // 接收输入
int diff = num1 - num2; // 计算并存入新抽屉
cout << diff; // 输出结果
```
4. **编译运行**:按下 F11。如果有报错,不要慌,检查是不是漏了分号,或者 `>>` 和 `<<` 的方向写反了。
5. **输入测试数据,验证结果**:在弹出的黑框里输入测试用例 `2 3`,看看结果是不是 `-1`。
6. **修正错误**:如果输出不对(比如输出了 5),说明语法没问题,但是**逻辑错了**。回去检查代码,是不是把减号写成加号了?修改后重新测试,直到完全正确为止。
@@ -0,0 +1,37 @@
### **C++ `cin` 输入 课后习题 - 答案**
#### **一、 填空题**
1. Console Input (或 控制台输入)
2. `>>` , 提取运算符
3. 输入 , 处理
4. 暂停 (或 阻塞)
5. 空格 , 回车
6. 定义
7. 放进
#### **二、 单项选择题**
1. **D**. `cin` 的核心就是获取键盘输入。
2. **C**. `cin` 使用提取运算符 `>>`,方向是从 `cin` 流向变量。
3. **C**. 链式输入使用 `>>` 连接多个变量。
4. **C**. `cin` 默认使用空白字符(空格、回车等)作为分隔符,逗号不是空白字符,无法正确分割。
5. **B**. `cin` 使得程序可以处理运行时才给定的数据,变得通用和灵活。
6. **B**. 程序先定义变量,然后通过 `cin` 获取值,再进行计算和输出,是完整的“输入-处理-输出”流程。
7. **C**. 两种写法在功能上完全相同,都能读取两个变量,但链式写法更为常用和简洁。
8. **B**. 程序能运行但结果不对,说明语法正确(不是CE),但计算或处理的思路(逻辑)错了。
9. **B**. `cin >> a;` 只会读取一个整数。它读到 `5`,遇到空格,就认为第一个数的输入结束了,所以 `a` 的值是 `5`。`6` 会留在输入缓冲区中等待下一次 `cin` 读取。
10. **C**. `int a, b;` 定义变量,`cin >> a >> b;` 使程序暂停,等待输入。
#### **三、 判断题**
1. × ( `c` 代表 "Console" (控制台)。)
2. √ (必须先准备好“抽屉”,才能往里面放东西。)
3. √ (`cin` 是输入,`cout` 是输出,方向和作用都相反。)
4. √ (`cin` 在读取数据前会跳过所有空白字符。)
5. × (回车也是一种空白分隔符,所以可以一个数字一行,分两行输入。)
6. √ (这是讲义中强调的程序设计基本结构。)
7. √ (这正是引入 `cin` 的核心价值。)
8. × (讲义中的6步法强调,应该先整理思路,再翻译成代码。)
9. √ (提取运算符 `>>` 的作用就是将读取到的值赋给变量。)
10. × ( `cout` 应该使用插入运算符 `<<`,正确的写法是 `cout << "请输入一个数字";`。)
@@ -0,0 +1,95 @@
### **C++ `cin` 输入 课后习题**
姓名: \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_
#### **一、 填空题**
1. 在C++中,`cin` 是 \_\_\_\_\_\_\_\_\_\_\_\_\_\_ 的英文缩写,它的主要作用是接收用户的键盘输入。
2. `cin` 使用的运算符是 \_\_\_\_\_\_\_\_\_\_,这个运算符被称为 \_\_\_\_\_\_\_\_\_\_,它的箭头方向形象地表示数据从键盘流向变量。
3. 一个有输入功能的程序,其基本流程可以分为三个步骤:\_\_\_\_\_\_\_\_\_\_、处理和输出。
4. 当程序执行到 `cin >> a;` 语句时,会\_\_\_\_\_\_\_\_\_\_运行,并等待用户输入数据。
5. `cin` 通过空白字符来区分多个输入数据,最常见的两种空白字符是\_\_\_\_\_\_\_\_\_\_和\_\_\_\_\_\_\_\_\_\_。
6. 在使用 `cin >> num;` 之前,必须先\_\_\_\_\_\_\_\_\_\_变量 `num`,为输入的数据准备好存放空间。
7. 讲义中用生活中的例子做比喻,把变量比作“抽屉”,那么 `cin` 的作用就是把外面的数据\_\_\_\_\_\_\_\_\_\_“抽屉”里。
#### **二、 单项选择题**
( &nbsp; ) 1. 在C++中,`cin` 的核心功能是什么?
A. 在屏幕上打印文字和符号
B. 让程序暂停指定的时间
C. 定义新的变量类型
D. 从键盘读取数据并存入变量
( &nbsp; ) 2. 下面哪条语句可以正确地从键盘读取一个整数并存放到变量 `score` 中?
A. `cin << score;`
B. `cout >> score;`
C. `cin >> score;`
D. `cout << score;`
( &nbsp; ) 3. 如果要用一条语句连续读取用户的两个整数,分别存入变量 `width` 和 `height`,应该怎么写?
A. `cin >> width, height;`
B. `cin >> width; height;`
C. `cin >> width >> height;`
D. `cin << width << height;`
( &nbsp; ) 4. 对于语句 `cin >> x >> y;`,用户在键盘上**不正确**的输入方式是?
A. 输入 `10`,按空格键,再输入 `20`,按回车键
B. 输入 `10`,按回车键,再输入 `20`,按回车键
C. 输入 `10,20`,按回车键
D. 输入 `10`,按多个空格键,再输入 `20`,按回车键
( &nbsp; ) 5. `cin` 这个工具主要解决了程序中的什么根本性问题?
A. 计算速度太慢的问题
B. 只能计算和处理“写死”在代码里的固定数据的问题
C. 无法输出中文的问题
D. 代码必须从 `main` 函数开始的问题
( &nbsp; ) 6. 阅读以下代码,它的功能是什么?
```cpp
int base, height;
cin >> base >> height;
int area = base * height / 2;
cout << area;
```
​ A. 计算一个固定三角形的面积
​ B. 输入两个整数作为底和高,然后计算并输出三角形的面积
​ C. 只输入两个整数,不进行任何计算
​ D. 这段代码有语法错误,无法运行
( &nbsp; ) 7. `cin >> a; cin >> b;` 和 `cin >> a >> b;` 这两种写法是什么关系?
A. 前者正确,后者错误
B. 两者功能完全不同
C. 两者功能等价,但后者更简洁
D. 后者正确,前者错误
( &nbsp; ) 8. 编程的6个步骤中,如果在“输入测试数据,验证结果”时发现输出与预期不符,这通常说明发生了什么错误?
A. 语法错误
B. 逻辑错误
C. 编译错误
D. 硬件故障
( &nbsp; ) 9. 假如程序是 `int a; cin >> a;`,而用户输入了 `5 6` 然后按回车,那么变量 `a` 中存储的值是多少?
A. 56
B. 5
C. 6
D. 11
( &nbsp; ) 10. `int a, b; cin >> a >> b;` 这两行代码执行时,程序的行为是?
A. 立刻计算 a+b 的值
B. 在屏幕上输出 a 和 b
C. 定义了两个变量,然后暂停等待用户输入两个由空白字符隔开的数据
D. 定义了两个变量,然后程序直接结束
#### **三、 判断题 (对的打“√”,错的打“×”)**
1. `cin` 的 `c` 代表 "C++",`in` 代表 "input"。 ( &nbsp; )
2. 必须先定义变量,然后才能使用 `cin` 把数据存入这个变量。 ( &nbsp; )
3. `cin` 使用的运算符是 `>>`,`cout` 使用的运算符是 `<<`,两者方向相反,作用也相反。 ( &nbsp; )
4. `cin` 会自动忽略输入数据前多余的空格、Tab键或回车。 ( &nbsp; )
5. 如果写 `cin >> x >> y;`,用户必须在同一行内输入两个数字,不能换行输入。 ( &nbsp; )
6. “输入 -> 处理 -> 输出”是解决编程题目的三个基本步骤。 ( &nbsp; )
7. 一个好的程序应该通过 `cin` 接收用户的任意合法输入,而不是每次都让用户去修改源代码。 ( &nbsp; )
8. 在分析一个编程问题时,正确的做法是先动手写代码,再边写边想思路。 ( &nbsp; )
9. `cin >> a;` 这行代码执行后,变量 `a` 的值就变成了用户刚刚从键盘输入的值。 ( &nbsp; )
10. `cout >> "请输入一个数字";` 这行代码是正确的。 ( &nbsp; )
@@ -0,0 +1,143 @@
### **C++ 字符类型 `char` 与转义字符 讲义**
#### **第一部分:字符类型 `char` (存储单个字符的盒子)**
##### **1. 问题引入:除了数字,程序还能处理什么?**
在之前的学习中,我们已经学会了用 `int` 存储整数,用 `double` 存储小数。但我们的世界是由丰富多彩的文字和符号构成的。比如,我们要编写一个程序,实现一个简易计算器,用户会输入 `7 * 2` 这样的算式。
* `7` 和 `2`,我们可以用 `int` 类型的变量来存储。
* 但是中间的那个乘号 `*` 呢?它不是一个数字,我们该用什么类型的“盒子”来装它呢?
这时候,`char` 类型就登场了。
##### **2. 什么是 `char` 类型?**
`char` 是 "character" (翻译:字符) 的缩写。它是一种专门用来存放**单个字符**的数据类型。
你可以把它想象成键盘上的**任意一个按键**,它可以是:
* 一个英文字母 (大写或小写): `'A'`, `'b'`, `'Z'`
* 一个数字字符: `'0'`, `'1'`, `'9'` (注意:这和数字 `0, 1, 9` 是不同的)
* 一个标点或符号: `','`, `'.'`, `'?'`, `'+'`, `'*'`
* 一个空格: `' '`
##### **3. 如何在 C++ 中使用 `char`?**
`char` 的使用方式和 `int` 基本一致,但有一个**极其重要**的区别:
> **在为 `char` 变量赋值或进行比较时,字符值必须被一对单引号 `' '` 包围。**
* **正确的写法**:
```cpp
char c1 = 'A'; // 正确!用单引号包围
char c2 = '*';
char c3 = ' '; // 空格也是一个字符
```
* **错误的写法**:
```cpp
char c4 = A; // 错误!编译器会认为 A 是一个变量名,而不是字符'A'
char c5 = "A"; // 错误!双引号 "" 是用来表示字符串的,不能用于单个字符
```
##### **4. 实战演练:简易计算器**
* **问题**:输入两个整数和一个乘号 `*`,输出这两个整数的乘积。
* *输入样例*: `7 * 2`
* *输出样例*: `14`
* **逻辑分析**:
1. **准备“盒子”**:我们需要两个盒子装整数,一个盒子装中间的 `*` 号。
* `int num1, num2;`
* `char op;` (`op` 是 operator/操作符的英文缩写)
2. **接收“原料”**:C++ 的 `cin` 非常智能,它会根据你变量的顺序和类型,自动读取并分割输入。
* `cin >> num1 >> op >> num2;` 当用户输入 `7 * 2` 时,`cin` 会把 `7` 存入 `num1`,把 `*` 存入 `op`,把 `2` 存入 `num2`。
3. **加工计算**:`int result = num1 * num2;`
4. **交付产品**:`cout << result;`
* **完整代码**:
```cpp
#include <iostream>
using namespace std;
int main() {
int num1, num2;
char op; // 准备一个char类型的盒子来装运算符
cout << "请输入一个乘法表达式 (如 7 * 2): ";
cin >> num1 >> op >> num2;
int result = num1 * num2;
cout << "计算结果是: " << result << endl;
return 0;
}
```
---
#### **第二部分:转义字符**
##### **1. 观察代码**
我们已经知道,放在双引号 `""` 里的内容,通常会被原样输出。但请观察以下代码:
```cpp
cout << "hello\nworld";
```
按照我们的直觉,屏幕上应该会打印出 `hello\nworld`。但实际运行结果却是:
```
hello
world
```
我们发现:
1. 字符 `\` 和 `n` 在屏幕上“神秘地消失”了。
2. `world` 被打印到了新的一行。
**原因解析**:这并不是 Bug,而是因为 `\n` 是 C++ 语法中的一个**转义字符。
##### **2. 转义字符的原理与应用**
* **什么是转义字符?**
转义字符是一种特殊的符号组合,它以反斜杠 `\` 开头,用于在代码中表示一些**无法直接打印的控制功能**(如换行、制表符)或**具有特殊语法含义的字符本身**(如双引号、反斜杠自己)。
你可以把反斜杠 `\` 想象成一个“**魔法棒**”。当它出现在一个字符前面时,它会**改变**后面那个字符的本来面目,赋予它一个特殊的魔法效果。
* **常用转义字符对照表**
| 转义符 | 术语 | 实际作用与说明 |
| -------- | -------------- | ------------------------------------------------------------ |
| **`\n`** | **换行符** | 效果:**换行**。将光标移动到下一行的行首。 |
| **`\t`** | **水平制表符** | 效果:**对齐**。将光标向前跳跃一个制表位的距离(通常相当于几个空格)。 |
| **`\\`** | **反斜杠字符** | 效果:让它变回一个普通的反斜杠字符并打印出来,即输出一个反斜杠本身。 |
| **`\"`** | **双引号字符** | 效果:让它变回一个普通的双引号字符并打印出来,即输出一个双引号本身。 |
| **`\'`** | **单引号字符** | 用于打印单引号本身。 |
##### **3. 综合应用实例**
* **任务目标**:在屏幕上输出下面这句话:
> `小明说:"what is \n"`
* **逻辑推演**:
1. **基础结构**:首先,整句话是一个字符串需要通过 `cout` 输出,那么需要用一对双引号包围。
`cout << "小明说:"what is \n"";` <-- 如果这样直接写,就全部乱套了!
2. **解决内部双引号冲突**:目标文本中的双引号 `"` 会让编译器误以为字符串提前结束了。我们需要用 `\"` 来告诉编译器:这个双引号只是一个普通字符,我想要输出它本身,不是字符串的边界。
3. **解决 `\` 的冲突**:我们想输出 `\` 本身。于是我们需要用 `\\` 来打印出那个反斜杠本身。
`cout << "小明说:\"what is \\n\"";` <-- 解决!
* **C++ 实现代码**:
```cpp
#include <iostream>
using namespace std;
int main() {
cout << "小明说:\"what is \\n\"" << endl;
return 0;
}
```
#### **总结**
* **`char`** 是用来存储**单个**字符的“小盒子”,它的值必须用**单引号`''`**括起来。
* **转义字符**以反斜杠 `\` 开头,它能赋予紧随其后的字符一个**特殊的功能**或让其**变回普通字符**。
* `\n` (换行) 和 `\t` (制表) 是最常用的功能性转义字符。
* 当你需要在字符串中打印 `"` 或 `\` 本身时,必须在它们前面再加上一个 `\`,即使用 `\"` 和 `\\`。
@@ -0,0 +1,142 @@
# C++字符与 ASCII 码 讲义
## 1. 概念
在计算机的世界里,一切皆是 0 和 1(二进制)。计算机天生只认识数字,不认识字母、标点符号。
为了让计算机能显示和处理文字,人类制定了一套规则:**给每一个字符指定一个唯一的数字编号**。
* **字符 (Character)**:我们在屏幕上看到的符号(如 `'A'`, `'@'`, `'1'`)。
* **ASCII 码**:一种最基础的编码标准,规定了字符和数字之间的对应关系。
---
## 2. C++ 中的字符类型 (`char`)
在 C++ 中,我们学习了如何储存一个整数或者小数,但是字符是使用 `char` 关键字来定义并储存字符变量的。
### 2.1 基本语法
* **书写方式**:必须使用**单引号** `' '` 括起来。
* **本质**:`char` 类型在内存中实际上存储的是一个**整数**(即该字符对应的 ASCII 码值)。
```cpp
char letter = 'A'; // 正确
char numChar = '5'; // 正确,这是字符5,不是数字5
// char error = "A"; // 错误!双引号代表字符串
```
### 2.2 使用 `char`
**题目描述:请你实现普通计算器的功能,输入两个整数和一个*,输出这两个整数的乘积。**
**样例输入: 7 * 2**
**样例输出: 14**
---
**逻辑解析:**
- **定义容器**:我们需要两个 `int` 类型的变量来存放参与运算的数字,**以及一个 `char` 类型的变量来存放中间的运算符 `*`**,我们就可以定义:`int num1, num2; char ch; `
- **获取数据**:接受用户输入,将三个值分别放入三个变量中,并且按照顺序读取 `cin >> num1 >> ch >> num2;`
- **读取 `num1`**:读取的第一个是整数变量,于是`cin` 接着期待一个整数,例如它读取了 `7`,接着遇到了空格。所以它会**自动结束读取**,将 `7` 存入 `num1` 中。
- **读取 `op`**:接着是一个字符类型变量,于是`cin` 接着期待一个字符。拿到了字符 `*`,并存入字符变量 `op` 中。
- **读取 `num2`**:最后,`cin` 再次期待一个整数。它跳过空格,读取到数字 `2`,存入 `num2`。
- **计算结果:**`num1` 与 `num2` 已经存入了输入的两个整数,最后仅需按照题目要求输出这两个整数的乘积即可:`cout << num1 * num2;`
## 3. 什么是 ASCII 码?
**全称**:American Standard Code for Information Interchange(美国信息交换标准代码)。
因为计算机却只认识数字,不认识字符,那计算机怎么存储“Hello”这个单词呢?
为了解决这个问题,人类制定了一张**强制转换表**,这就是 **ASCII** **码表**。 它规定了每一个符号对应一个特定的整数。字符在计算机内部,本质上就是一个整数。
它是一张“对照表”,规定了 128 个字符对应的数字。
- 当你按下键盘上的 `A`。
- 计算机查表:哦,`A` 对应的是 `65`。
- 计算机存储:在内存里存下 `65` 。
- 当你 `cout` 时:计算机读取 `65`,查表发现是 `A`,然后就输出一个 `A` 在屏幕上
### 3.1 ASCII 码表的构成
1. **0 - 31 (控制字符)**:不可打印,用于控制外围设备,这部分**了解**即可,一般不会用到。
* 例如在我们键盘上的:换行、回车、响铃、退格。
2. **32 - 126 (可打印字符)**:键盘上能打出来的符号。
* 包括:空格、标点、数字、大写字母、小写字母。**这部分需要知道掌握**。
3. **127 (Delete)**:删除控制符,**了解**即可。
---
## 4. 必须记住的关键 ASCII 值
你不需要背诵整个表,但以下几个数值应当记住,因为它们常用于编程逻辑中。
| 字符类别 | 起始字符 | ASCII 值 | 结束字符 | ASCII 值 | 备注 |
| :----------- | :------: | :------: | :------: | :------: | :-------------------------------- |
| **数字** | `'0'` | **48** | `'9'` | **57** | 注意:`'0'` 和 `0` 不是同一个东西 |
| **大写字母** | `'A'` | **65** | `'Z'` | **90** | |
| **小写字母** | `'a'` | **97** | `'z'` | **122** | |
### 规律总结:
1. 数字、大写字母、小写字母都是**连续**排列的。
2. **大小写转换规律**:小写字母的 ASCII 值比对应的大写字母大 **32**。
* `'a' - 'A' = 32`
* `'A' + 32 = 'a'`
---
## 5. 字符与整数的互换 (C++ 的自动类型转换特性)
在 C++ 中,其实`char` 和 `int` 可以自由转换和运算。
1. 源类型向目标类型转换时。如果目标类型能够容纳源类型的值,且转换是安全的,编译器就会自动完成。
- **例如**:`int` 赋给 `double` 是安全的(`int` 转换为 `double`)。
- **但请注意:** `double` 赋给 `int` 时,虽然编译器会尝试转换(截断小数部分),但这通常被认为是**不安全的**,因为它会丢失精度。在严格的编译环境下可能会有警告,甚至在某些情况下需要显式转换(后续会讲解强制类型转化)。
- **整型和浮点型混合运算时,整型会向浮点型转换以避免数据丢失**。**核心原则是** “向高精度、大范围类型转换”,以避免数据丢失。例如,`int` 和 `double` 相加时,`int` 会被转换为 `double`。
简单来说,C++的自动类型转换是尽力让你在不同类型之间进行操作时,得到一个合理的结果,并且尽量不丢失数据。
### 5.1 查看字符的 ASCII 码
**使用 `int` 类型的变量来接住 `char` 类型的值。**
```cpp
#include <iostream>
using namespace std;
int main() {
char c = 'A';
cout << "字符: " << c << endl; // 输出 A
int num = c;
cout << "ASCII值: " << num << endl; // 输出 65
return 0;
}
```
### 5.2 字符运算 (算术操作)
**因为字符本质是整数(通过ASCII码来进行对照),所以可以进行加减乘除。**
==**案例 1:大小写转换(重要,必须掌握)**==
利用小写与小写字符中的差值为 32 进行转化。
```cpp
char upper = 'B';
char lower = upper + 32; // 66 + 32 = 98 ('b')
cout << lower << endl; // 输出 b
```
==**案例 2:数字字符 转 整数数字**==
这是算法题中非常常见的操作。因为数字字符在ASCII码里是连续的,所以任意一个 字符数字 和 字符0 之间的差值就是字符数字对应的整数数字。
例如`'7' - '0' = 7, '4' - '0' = 4, '0' - '0' = 0`。
```cpp
char c_num = '8';
int i_num = c_num - '0'; // '8'(56) - '0'(48) = 8
cout << i_num << endl; // 输出数字 8
```
@@ -0,0 +1,168 @@
## **C++ 类型转换 讲义**
### 1. 引言
* **字符的储存**
字符 `'A'` 在计算机底层又是用哪个数字存储的呢?计算机的本质是处理数字,我们看到的所有文本、字符,在它眼中都是一个个特定的数字。最著名的编码表就是 **ASCII** (美国信息交换标准代码),在书本P17页有部分的ASCII编码表可做参考。
### 2. 核心思想
**自动类型转换**
我们有一个整数 `int number = 65;`。我们想得到它对应的字符。一个想法是:C++ 那么聪明,我直接把 `int` 赋值给 `char` 会怎么样?其实在 C++ 中,`char` 和 `int` 可以自由转换和运算。
```cpp
int number = 65;
char c = number; // C++ 允许这样做,它会自动转换
cout << c; // 输出 'A'
```
这种由编译器自动完成的转换,叫做 **自动类型转化(隐式转换)**。在很多简单场景下,它完全没有问题!但是,这种有时会隐藏一些问题。如果代码很复杂,**其他人读到 `char c = 65;` 时,可能会疑惑:这是一个笔误吗?还是故意这么写的?为什么两边的数据类型不一样?**
因为正常情况下,**赋值符号的右边的数据类型**应该和**左边的变量数据类型相匹配**。
但是有些情况也可以不一致。源类型向目标类型转换时(例子中 `char c = number;` 源类型就是 `int` , 目标类型是`char`)。如果源类型和目标类型不一致,**在编译器知道怎么转换的情况下,会进行自动类型转换!**
- **例如**:`int` 赋给 `double` 是安全的(`int` 转换为 `double`)。
- **但请注意:** `double` 赋给 `int` 时,虽然编译器会尝试转换(截断小数部分),但这通常被认为是**不安全的**,因为它会丢失精度(小数点后的数据没有了)。
- **整型和浮点型混合运算时,整型会向浮点型转换以避免数据丢失**。**核心原则是** “向高精度、大范围类型转换”,以避免数据丢失。例如,`int` 和 `double` 相加时,`int` 会被转换为 `double`。
==**简单来说,C++的自动类型转换是尽力让你在不同的数据类型之间进行操作时,得到一个合理的结果,并且尽量不丢失数据。**==
**强制类型转换(推荐使用!)**
为了让我们的代码意图更加清晰,我们常常需要**强制类型转换**。
这相当于我们明确地告诉编译器:**我需要在这里把这个值的类型变一下!**
在 C++ 中,==强制类型转换语法==是:
**`(目标类型) 变量名 或 数值`**
- 例1:要把变量 `int number` 转换为 `char` 类型,我们就可以写:`(char)number`。
- 例2:要把变量 `int number` 转换为 `double` 类型,我们就可以写:`(double)number`。
**请注意:**如果我们想对 `a + b` 这种==**整个表达式的计算结果**==进行转换时,**就必须**使用括号 `()` 将表达式完整地包裹起来,写成 `(char)(a + b)`,以此来明确地告诉编译器:先算括号里的,再把算出来的最终结果进行转化!
而不能写成 `(char)a + b`,如果这样写,**它会先把变量 `a` 转换为 `char` 类型**。然后再去去和变量 `b` 相加。和我们的目的:将 `a + b` 的结果转化为 `char` 类型就不符了。
**步骤拆解**
使用强制类型转换将数字转为字符的步骤很简单:
1. **准备一个整数**:定义一个 `int` 类型的变量,并存入一个在 ASCII 码范围内的数字。
2. **执行转换**:使用 `(char)(你的整数变量)` 来进行转换。
3. **存储结果**:将转换后的结果赋值给一个 `char` 类型的变量。
4. **输出验证**:打印输出这个 `char` 变量,看看结果是否符合预期。
### 3. 实例
* **具体案例**
让我们把数字 `97` 转换为它对应的 ASCII 字符。
* **分步演示**
1. **准备一个整数**:
```cpp
int number = 97;
```
2. **执行转换**:我们使用强制类型转换。
```cpp
(char)number // 这个表达式的结果就是字符 'a'
```
3. **存储结果**:
```cpp
char res = (char)number;
```
4. **输出验证**:
```cpp
cout << res; // 屏幕上将会打印出 a
```
### 4. 代码实现
现在,让我们把上面的步骤整合起来,写一个完整的程序。这个程序的作用是输入一个数字,输出这个数字在ASCII 码表中对应的字符。
* **完整代码**
```cpp
#include <iostream>
using namespace std;
int main() {
cout << "请输入一个整数 (例如 65 到 90 之间): ";
// 定义变量并接收用户的输入
int number;
cin >> number;
// 使用强制类型转换
// 将 int 类型的 number 转换为 char 类型
char ascii_char = (char)number;
// 输出结果
cout << "数字 " << number << " 在 ASCII 码表中对应的字符是: " << ascii_char << endl;
return 0;
}
```
### 5. 验证
让我们用几个例子来测试一下我们的程序,看看会发生什么。
* **正常情况**:
* 输入 `65`,输出 `'A'`。
* 输入 `97`,输出 `'a'`。
* 输入 `48`,输出 `'0'`。
* **常见问题**
* **问**:为什么不直接用 `char c = number;`?
* **答**:在简单情况下可以,但它属于自动类型转化转换,意图不明确。像 `(char)number` 这样的强制转换,能让你的代码意图更清晰,一眼就能让人知道你是故意这样做的。
* **问**:强制类型转换安全吗?
* **答**:不一定。比方说: `double` 强制转换为 `int` 类型时,虽然编译器会转换(但是会截断小数部分)。所以,在转换前你要对数据的范围有的认识。例如你想转化一个整数到`char`字符类型,那就要确保这个整数的数值在ASCII码表中有对应的字符,如果这个数字根本不存在对应的字符,那计算机就也不知道应该如何转化了。
---
### **6. C++ 字符大小写转换(两种办法)**
#### 一:直接观察法
* 观察 ASCII 码表,你会发现一个规律:
* `'A'` 是 65, `'a'` 是 97
* `'B'` 是 66, `'b'` 是 98
* ...
* `'Z'` 是 90, `'z'` 是 122
**任意一个相同字母的小写形式,其 ASCII 码值都比大写形式大 32!** (`'a' - 'A' = 97 - 65 = 32`)
基于这个规律,我们有实现方式:
* **==小写转大写==**:`大写字符 = 小写字符 - 32`
* **==大写转小写==**:`小写字符 = 大写字符 + 32`
* **案例:大小写转换**
```cpp
char upper = 'B';
char lower = upper + 32; // 66 + 32 = 98 ('b')
cout << lower; // 输出 b
```
#### **二:差值计算法**:
例如想要将大写字符 `'C'`转为小写
1. **计算偏移量**:首先,我们需要知道目标字母 `'C'` 相对于大写字母起点 `'A'` 的“位置”或“差值量”。
* 这个偏移量可以通过减法计算得出:`'C' - 'A'`。我们知道结果是 `2`。这告诉我们,`'C'` 是排在 `'A'` 后面的第2个字母(从0开始计数)。
2. **找到新起点**:我们的目标是小写字母,那么小写字母的“起点”是谁?是 `'a'`。
3. **应用偏移量**:我们在新的起点 `'a'` 上,加上刚才计算出的差值量 `2`,就能得到我们想要的小写字母。
* `'a' + ('C' - 'A')`
* `'a' + 2` --> 结果就是 `'c'`。
* **公式**:
* **大写转小写**:`小写字母 = 任意大写字母 - 'A' + 'a'`
* **小写转大写**:`大写字母 = 任意小写字母 - 'a' + 'A'`
### 总结
1. 字符在计算机底层是以数字(如 ASCII 码)存储的。
2. `char` 和 `int` 之间可以相互转换。
3. 使用 `(目标类型)值` 的形式可以进行**强制类型转换**,这能让代码的意图更清晰。
4. 进行类型转换时,要注意目标类型的**取值范围**,防止数据**溢出**,例如你想转化一个整数到`char`字符类型,那就要确保这个整数的数值在ASCII码表中有对应的字符,如果这个数字根本不存在对应的字符,那计算机就也不知道应该如何转化了。
5. 英文字母的大小写形式在 ASCII 码表中具有固定的数值差 (`32`)。
@@ -0,0 +1,32 @@
### **C++ 转义字符与字符类型 课后习题 - 答案**
#### **一、 填空题**
1. `char`
2. 单引号
3. `100`
4. `\\`
5. `\"Hi\"`
6. `':'`
#### **二、 单项选择题**
1. **C**. `char` 类型的字面量必须用单引号包裹,且只能是单个字符。
2. **C**. `\n` 是换行符,会让 `Tom` 显示在下一行。
3. **B**. 反斜杠 `\` 本身是转义字符,要输出它自身,需要写成 `\\`。
4. **A**. `cin` 会依次读取一个整数存入 `a`,一个字符存入 `op`,一个整数存入 `b`。输入 `5+3` 时,`op` 会接收到字符 `'+'`。
5. **B**. `\"` 是双引号的转义序列,用于在字符串内部表示一个双引号字符。
6. **D**. `char` 变量只能存放单个字符,`'Go'` 包含两个字符,是错误的。
7. **A**. 程序读取一个整数 `h`,然后需要读取一个字符,最后读取一个整数 `m`。
8. **C**. `\\` 是 `\` 的转义序列,所以 `\\` 会让 `\` 失去转义功能,变回它本身。因此 `\\n` 会输出 `\n` 这两个字符。
#### **三、 判断题**
1. × (必须用单引号 `' '`。)
2. √ (两者最终在屏幕上看到的换行效果是一样的。)
3. √ (`cin` 默认通过空白字符(空格、回车等)分隔数据,读到 'A' 后遇到空格,就完成了对 `c` 的读取。)
4. √ (这正是转义字符的定义。)
5. × ( `char` 只能存放单个字符。)
6. √ (`cin` 会先读取数字部分 `99` 存入 `a`,然后接着读取非数字字符 `'A'` 存入 `c`。)
7. √ ( `"` 是特殊字符,在字符串中必须通过 `\"` 来表示。)
8. √ (如 `cin >> a >> op >> b;` 所示,`cin` 可以很灵活地连续读取不同类型的数据。)
@@ -0,0 +1,78 @@
### **C++ 转义字符与字符类型 课后习题**
姓名: \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_
#### **一、 填空题**
1. C++中,用于存放单个字符(如 'A', '?')的数据类型是 \_\_\_\_\_\_\_\_\_\_。
2. 在为 `char` 类型变量赋值时,该字符必须被一对 \_\_\_\_\_\_\_\_\_\_(填“单引号”或“双引号”)包围。
3. 代码 `cout << "Score:\n100";` 的输出结果是:第一行显示 `Score:`,第二行显示 \_\_\_\_\_\_\_\_\_\_。
4. 如果想在屏幕上显示出路径 `D:\Data`,那么在代码的字符串中应该写作 `D:________Data`。
5. 如果想在屏幕上显示出带引号的文字 `He said: "Hi"`,那么代码中表示 `"Hi"` 的部分应该写作 \_\_\_\_\_\_\_\_\_\_。
6. 对于代码 `int h; char c; cin >> h >> c;`,如果用户输入 `12:59` 并回车,那么整型变量 `h` 的值是 `12`,而字符型变量 `c` 的值是 \_\_\_\_\_\_\_\_\_\_。
#### **二、 单项选择题**
( &nbsp; ) 1. 下面哪个是定义 `char` 变量并正确赋值的语句?
A. `char c = "A";`
B. `char c = A;`
C. `char c = 'A';`
D. `char c = 'AB';`
( &nbsp; ) 2. 执行 `cout << "Name:\nTom";` 后,屏幕上会显示什么?
A. `Name:\nTom`
B. `Name: Tom`
C. 两行,第一行 `Name:`,第二行 `Tom`
D. `Name:Tom`
( &nbsp; ) 3. 哪句代码可以在屏幕上正确输出路径 `C:\` ?
A. `cout << "C:\";`
B. `cout << "C:\\";`
C. `cout << "C:/";`
D. `cout << 'C:\';`
( &nbsp; ) 4. 阅读以下代码,如果用户输入 `5+3` 并回车,变量 `op` 的值是多少?
```cpp
int a, b;
char op;
cin >> a >> op >> b;
```
​ A. `'+'`
​ B. `+`
​ C. `" "` (空格)
​ D. 程序会报错
( &nbsp; ) 5. 执行 `cout << "He said \"Go!\"";` 后,屏幕上会显示什么?
A. `He said Go!`
B. `He said "Go!"`
C. `He said \"Go!\"`
D. `He said: "Go!"`
( &nbsp; ) 6. 以下哪个**不能**被正确地赋值给一个 `char` 类型的变量?
A. `'?'`
B. `' '`
C. `'7'`
D. `'Go'`
( &nbsp; ) 7. 有代码 `int h, m; char c; cin >> h >> c >> m;`,为了让程序成功读入小时 `11` 和分钟 `59`,不正确的输入格式是?
A. `11 59`
B. `11:59`
C. `11,59`
D. `11;59`
( &nbsp; ) 8. 执行 `cout << "\\n";` 后,屏幕上会显示什么?
A. 一个空行
B. `n`
C. `\n`
D. `\`
#### **三、 判断题 (对的打“√”,错的打“×”)**
( &nbsp; ) 1. 在C++中,定义一个字符变量时,字符必须用双引号 `"` 包起来。
( &nbsp; ) 2. `\n` 和 `endl` 都能在 `cout` 中实现换行的视觉效果。
( &nbsp; ) 3. 对于 `char c; cin >> c;`,如果用户输入 `A B` 并回车,变量 `c` 的值会是 `'A'`。
( &nbsp; ) 4. 转义字符 `\` 本身通常不会被显示,它的作用是改变其后字符的含义。
( &nbsp; ) 5. 一个 `char` 类型的变量可以存放一个单词,比如 `'Hello'`。
( &nbsp; ) 6. 对于 `int a; char c; cin >> a >> c;`,如果用户输入 `99A`,那么 `a` 的值是 `99`,`c` 的值是 `'A'`。
( &nbsp; ) 7. 想输出双引号 `"`,代码必须写成 `cout << "\"";`。
( &nbsp; ) 8. `cin` 可以一次性读取不同类型的变量,例如 `int` 和 `char`。
@@ -0,0 +1,28 @@
### 参考答案
#### **一、 填空题**
1. `char`
2. 单引号
3. `66`
4. `32`
5. `5`
6. `'+'`
#### **二、 单项选择题**
1. C
2. C
3. B (字符'C'的ASCII码是67,加1后是68,68对应的字符是'D')
4. B
5. B
6. A
#### **三、 判断题**
1. × (一个是字符,一个是数字,它们的ASCII码和数值都不同)
2. √
3. √
4. × (从'A'到'Z',ASCII码是递增的)
5. √
6. × (`char` 只能存放单个字符)
@@ -0,0 +1,70 @@
### C++ 字符与 ASCII 码 课后习题
姓名: \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_
#### **一、 填空题**
1. 在 C++ 中,我们使用关键字 \_\_\_\_\_\_\_\_ 来定义一个存放单个字符的变量。
2. 定义一个字符变量时,字符本身必须用 \_\_\_\_\_\_\_\_ (填“单引号”或“双引号”) 括起来。
3. 字符 `'A'` 对应的 ASCII 码值是 `65`,那么字符 `'B'` 对应的 ASCII 码值是 \_\_\_\_\_\_\_\_。
4. 小写字母 `'a'` 的 ASCII 码值比大写字母 `'A'` 的 ASCII 码值大 \_\_\_\_\_\_\_\_。
5. 阅读代码 `char c = '5'; int n = c - '0';`,执行后,整型变量 `n` 中存放的值是 \_\_\_\_\_\_\_\_。
6. 在 `cin >> num1 >> op >> num2;` 中,如果用户输入 `10 + 20`,那么字符变量 `op` 中存入的值是 \_\_\_\_\_\_\_\_。
#### **二、 单项选择题**
( ) 1. 下列哪个是**正确**的字符变量定义语句?
A. `char c = "A";`
B. `char c = A;`
C. `char c = 'A';`
D. `int c = 'A';`
( ) 2. 执行 `int ch = 'a'; cout << ch;` 后,屏幕上会显示什么?
A. `a`
B. `A`
C. `97`
D. `65`
( ) 3. 阅读以下代码:
```cpp
char letter = 'C';
letter = letter + 1;
cout << letter;
```
​ 程序的输出结果是?
​ A. `C`
​ B. `D`
​ C. `67`
​ D. `68`
( ) 4. 如果想把大写字母 `'E'` 转换为对应的小写字母,正确的代码是?
A. `'E' - 32`
B. `'E' + 32`
C. `'E' - 'A'`
D. `'E' + 'a'`
( ) 5. 在计算机内部,`char` 类型的变量实际上存放的是什么?
A. 字符的形状
B. 字符对应的 ASCII 码(一个整数)
C. 一段文字
D. 一个小数
( ) 6. `int a; char op; cin >> a >> op;` 如果用户输入 `9*`,那么变量 `a` 和 `op` 的值分别是?
A. `a` 是 `9`,`op` 是 `'*'`
B. `a` 是 `'9'`,`op` 是 `'*'`
C. `a` 是 `9`,`op` 的值不确定
D. 读取会失败
#### **三、 判断题 (对的打“√”,错的打“×”)**
( ) 1. 在 C++ 中,字符 `'8'` 和整数 `8` 是完全一样的。
( ) 2. 计算机能识别和处理文字,是因为有一张像 ASCII 码这样的“字符-数字”对照表。
( ) 3. 数字字符是连续排列的,例如 `'1'` 的 ASCII 码比 `'0'` 的大 1。
( ) 4. 大写字母 `'Z'` 的 ASCII 码比 `'A'` 的小。
( ) 5. 因为字符本质上是数字,所以我们可以对 `char` 类型的变量进行加减运算。
( ) 6. `char c = 'ab';` 这样的写法是正确的。
@@ -0,0 +1,27 @@
### C++ 类型转换 课后习题 - **答案**
#### **一、 填空题**
1. ASCII
2. 自动类型
3. 强制类型
4. 目标类型
5. 32
6. `(a + b)`
#### **二、 单项选择题**
1. B 2. C 3. A 4. B 5. B 6. C 7. C 8. B 9. C 10. C
#### **三、 判断题**
1. × (保存的是对应的数字,即ASCII码)
2. × (这是自动类型转换/隐式转换)
3. √
4. √
5. × (会丢失小数部分,是不安全的操作)
6. × (前者先转换x再加y,后者先算x+y再转换结果)
7. √
8. × (转换前需要了解数据范围,否则可能得到预期外的结果)
9. √
10. √
@@ -0,0 +1,65 @@
### C++ 类型转换 课后习题
姓名: \_\_\_\_\_\_\_\_\_\_\_\_\_
#### **一、 填空题**
1. 计算机在存储字符(如 `'A'`)时,实际上存的是一个数字,这个数字是根据 \_\_\_\_\_\_\_\_\_\_\_\_\_ 码表来确定的。
2. 例如`int a = 'A';`赋值符两边的类型不一致的情况,会由编译器完成类型转换,叫做 \_\_\_\_\_\_\_\_\_\_\_\_\_ 转换。
3. 为了让代码的意图更清晰,我们通过 `(目标类型)变量名/数值` 的格式去进行类型类型的方式,叫做 **\_\_\_\_\_\_\_\_\_\_\_\_\_**转换。
4. 强制类型转换的语法格式是:`(`\_\_\_\_\_\_\_\_\_\_\_\_\_`)变量名/数值`。
5. 根据ASCII码表的规律,任意一个大写英文字母和它对应的小写字母,它们对应的数字相差 \_\_\_\_\_\_\_\_\_\_\_\_\_。
6. 要把一个表达式 `a + b` 的计算**结果**整体转换为 `char` 类型,正确的写法是 `(char)`\_\_\_\_\_\_\_\_\_\_\_\_\_。
#### **二、 单项选择题**
( ) 1. 执行 `cout << (char)65;` 这行代码,屏幕上会输出什么?
A. 65 B. 'A' C. 'a' D. 无法输出
( ) 2. 执行 `cout << (int)'a';` 这行代码,屏幕上会输出什么?
A. 'a' B. 65 C. 97 D. 32
( ) 3. 要将大写字母 `'C'` 转换为小写字母 `'c'`,正确的计算方法是?
A. `'C' + 32` B. `'C' - 32` C. `'C' + 'a'` D. `'C' - 'A'`
( ) 4. 要将小写字母 `'z'` 转换为大写字母 `'Z'`,正确的计算方法是?
A. `'z' + 32` B. `'z' - 32` C. `'z' + 'A'` D. `'z' - 'a'`
( ) 5. 当一个 `double` 类型的变量(如 `3.14`)被转换为 `int` 类型时,会发生什么?
A. 四舍五入,变为 3
B. 丢失小数部分,变为 3
C. 四舍五入,变为 4
D. 程序会报错
( ) 6. 表达式 `(char)('B' + 1)` 的计算结果是什么?
A. 'B' B. 'A' C. 'C' D. 2
( ) 7. 相比于 `char c = 97;`,使用 `char c = (char)97;` 这种写法的优点是?
A. 运行速度更快
B. 程序占用的内存更小
C. 代码的意图更清晰明确
D. 没有任何区别
( ) 8. 差值计算法中,`'D' - 'A'` 这个表达式的含义是?
A. 字母D减去字母A
B. 计算D和A的ASCII码值的差
C. 这是一个错误写法
D. 结果等于 `'C'`
( ) 9. 当一个 `int` 类型的数和一个 `double` 类型的数做加法时,`int` 类型会自动转换为哪个类型?
A. `char` B. `int` C. `double` D. 不会转换
( ) 10. `cout << (char)48;` 会在屏幕上输出什么字符?
A. 'a' B. 'A' C. '0' D. '1'
#### **三、 判断题 (对的打“√”,错的打“×”)**
( ) 1. 计算机在保存字符 `'A'` 时,就是保存了字母A的图片信息。
( ) 2. `char c = 65;` 这种写法属于强制类型转换。
( ) 3. 在ASCII码表中,所有小写字母对应的数字都比对应的大写字母要大。
( ) 4. 表达式 `'a' - 'A'` 的计算结果是 `32`。
( ) 5. 把一个小数(`double`)赋值给一个整数(`int`)是一种安全的操作,不会丢失任何数据。
( ) 6. `(char)x + y` 和 `(char)(x + y)` 的计算过程和结果是完全一样的。
( ) 7. `'Y' + 32` 的计算结果是小写字母 `'y'`。
( ) 8. 使用 `(char)num` 进行强制类型转换前,我们不需要关心 `num` 的值是多少,转换总是安全的。
( ) 9. `'a' + ('C' - 'A')` 这个表达式可以把大写字母 `'C'` 转换为小写字母 `'c'`。
( ) 10. 字符不仅可以和数字进行转换,字符之间也可以进行加减运算。
@@ -0,0 +1,283 @@
### **C++ 格式化输入与输出 讲义**
#### **一、 引言**
##### **问题引入:数字反转**
【书本P21页 例2-7】我们来看一个问题:
> 输入一个三位浮点数,例如 `123.4`,要求把这个数字彻底翻转过来,变成 `4.321` 并输出。
乍一看,这个问题似乎很难下手。我们熟悉的 `cin` 只能整个地读取这个数字,`cout` 也只能整个地输出。我们如何能把——`1`、`2`、`3`、`.`、`4`——拆开,再按新的顺序重新组合呢?
---
#### **二、 解法一:数学运算**
在揭晓新工具之前,我们先用已有的知识尝试解决。
##### **思路铺垫**
对于 `123.4`,最碍事的就是那个小数点。如果我们能先把它变成整数 `1234`,问题就简化成了“整数拆分”。
##### **核心工具:提取器与削减器**
我们回顾一下拆分整数的两个工具:
1. **个位的提取器 (`% 10`)**
* **作用**:获取一个整数的**最右边一位**。
* **原理**:任何整数除以10的**余数**,正好就是它的个位数。
* **示例**:`1234 % 10` 结果是 `4`。
2. **数字的削减器 (`/ 10`)**
* **作用**:**砍掉**一个整数的**最右边一位**。
* **原理**:在C++中,`整数 / 整数` 的结果会**直接舍弃小数部分**。
* **示例**:`1234 / 10` 结果是 `123`。
##### **步骤拆解**
1. **第一步(提取)**:使用 **提取器 (`% 10`)** 获得当前数字的个位数。
2. **第二步(削减)**:使用 **削减器 (`/ 10`)** 砍掉个位数,得到一个更小的数,为下一次操作做准备。
---
**具体案例**
让我们来手动拆解整数 `479`。
**分步演示**:
* **初始状态**: 我们有一个整数 `n = 479`。
* **第一轮操作 (处理 `479`)**:
1. **提取**: `479 % 10` -> 我们得到了数字 **`9`**。
2. **削减**: `479 / 10` -> `n` 现在变成了 **`47`**。
* *我们成功地把 `9` 从 `479` 中分离了出来,并且得到了一个更简单的问题:如何拆解 `47`。*
* **第二轮操作 (处理 `47`)**:
1. **提取**: `47 % 10` -> 我们得到了数字 **`7`**。
2. **削减**: `47 / 10` -> `n` 现在变成了 **`4`**。
* *小结:我们又分离出了 `7`,问题变得更简单了:如何拆解 `4`。*
* **第三轮操作 (处理 `4`)**:
1. **提取**: `4 % 10` -> 我们得到了数字 **`4`**。
2. **削减**: `4 / 10` -> `n` 现在变成了 **`0`**。
* *小结:我们分离出了最后的 `4`,`n` 变成了 `0`,说明拆解工作已全部完成!*
而对于我们的题目:**输入一个三位浮点数,例如 `123.4`,要求把这个数字彻底翻转过来,变成 `4.321` 并输出。**
我们就也能通过整数拆分的办法来解决了。
1. **预处理**:`double num = 123.4; int n = num * 10;` -> 得到整数 `1234`。
2. **逐位拆分**:
* `int d = n % 10;` // d = 4
* `int c = (n / 10) % 10;` // c = 3
* `int b = (n / 100) % 10;` // b = 2
* `int a = n / 1000;` // a = 1
3. **重新组合输出**:
* `cout << d << "." << c << b << a;`
**结论**:通过整数拆分的方法可以解决本问题,且一定要掌握通过数学运算拆分整数的办法。
---
#### **常见问题**
1. **问:对一个个位数(比如 `8`)使用这两个工具会怎样?**
* **答**:完全符合规则,不会出问题!
* **提取器**:`8 % 10` 的结果是 `8`。(8除以10,商0余8,成功提取出了最后一位数字 8)
* **削减器**:`8 / 10` 的结果是 `0`。(8除以10,整数商是0,成功削减了最后一位数字 8)
2. **问:如果数字里有 `0` 呢?比如 `205`?**
* **答**:规则同样适用!
* **第一轮**: `205 % 10` -> `5`;`205 / 10` -> `20`。
* **第二轮**: `20 % 10` -> `0`;`20 / 10` -> `2`。
* **第三轮**: `2 % 10` -> `2`;`2 / 10` -> `0`。
---
#### **要点回顾**
1. **个位的提取器 (`% 10`)**:它的作用就是帮你**看到并取走**一个整数最右边的那一位。
2. **数字的削减器 (`/ 10`)**:它的作用就是**砍掉**一个整数最右边的那一位,让数字变小。
3. 而且“提取”后必须“削减”,这样才能为处理下一位数字做准备。它们总是成对出现。
---
#### **三、 `printf` **
##### **核心概念与语法**
`printf` 的全称是 **Print Formatted(格式化打印)**。
它的作用是:**先写好一段带有“空位”的模板句子,然后再把变量按顺序填入这些空位中。**
**语法格式:**
> `printf("包含格式说明符(占位符)的字符串", 变量1, 变量2, ...);`
##### **`printf` 的使用方法**
1. **打印纯文本**
```cpp
printf("Hello, World!\n"); // \n 代表换行
```
2. **打印单个变量**
`printf` 在于用**格式说明符**(以`%`开头的占位符)去指定“空位”的类型,也就是先挖个坑占个座,之后我来告诉你什么数据会放在这里你进行输出就可以了。
```cpp
int age = 30;
// %d 是专门用来放整数的占位符
printf("我的年龄是 %d 岁。\n", age);
```
**逻辑解释:**
1. `"我的年龄是%d岁。\n"` 是输出的模板字符串。
2. `%d` 是一个占位符。
3. `printf` 会在输出时,自动按照顺序用后面 `age` 变量的值(30)去替换 `%d` 的位置。
3. **混合打印多个变量**
`printf` 也可以极其方便地在一句话中同时输出多个、多种类型的变量,而不需要像 `cin` 或 `cout` 那样反复使用 `<<` 拼接。
```cpp
int age = 15;
double height = 168.5;
char rank = 'S';
// 依次使用 %d, %lf, %c 作为占位符
printf("我今年%d岁,身高是%lf厘米,综合评级:%c\n", age, height, rank);
```
**核心规则**:
* **一一对应:** 字符串里有 3 个坑(`%d`, `%lf`, `%c`),后面就必须跟着 3 个变量(`age`, `height`, `rank`)。
* **按顺序入座:** `printf` 会严格按照从左到右的顺序,把第一个变量填入第一个占位符,第二个变量填入第二个占位符,以此类推。
* **类型必须匹配:** 第一个是整数类型 `age`,所以必须用 `%d`;第二个是小数类型 `height`,必须用 `%lf/%f`;第三个是字符类型 `rank`,必须用 `%c`。
##### **常用格式说明符(书本P24页,重要!)**
占位符的顺序必须与后面变量的顺序一一对应,且数据类型必须兼容!
| 占位符 | 对应数据类型 | 说明 |
| ---------- | -------------- | ------------------------------------------------------------ |
| **`%d`** | `int` | 打印整数 |
| **`%f`** | `float`、`double` | 打印浮点数 (默认保留6位小数) |
| **`%lf`** | `float`、`double` | 输出时与 `%f` 相同;小数位数由精度指定 |
| **`%c`** | `char` | 打印单个字符 |
| **`%.mf`** | `float/double` | **技巧:** 打印浮点数,并**精确保留m位小数**。例如 `%.2f` 就是保留两位。 |
### `cout` 与 `printf` 写法对比
| 操作目标 | `cout` 写法 | `printf` 写法 |
| ---------------- | ------------------------------- | ------------------------------- |
| 打印纯文本 | `cout << "输出的内容";` | `printf("输出的内容");` |
| 打印单个变量 | `cout << num1;` | `printf("%d", num1);` |
| 混合打印多个变量 | `cout << num1 << "和" << num2;` | `printf("%d和%d", num1, num2);` |
---
#### **四、 `scanf` **
##### **概念与语法**
`scanf` 的全称是 **Scan Formatted(格式化扫描/输入)**。
它的逻辑和 `printf` 基本一致,只不过从输出数据 变成了 输入数据:它会根据你提供的格式字符串模板,去键盘的输入中**抓取**对应的数据。
**语法格式:**
> `scanf("格式控制字符串", &变量1, &变量2, ...);`
##### **要注意 `scanf` 必须加 `&`(取地址符)**
**原理:**
* `cin` 很智能,你告诉它抽屉的名字(如 `age`),它就能自己找到。
* `scanf` 是一位老员工,你必须把这个抽屉在内存中的**具体物理地址**交给它,它才能把数据放进去。
那么在变量名前加上 `&`,就相当于提取了这个变量的地址,所以这个符号也被称为取地址符!
> **警告:** 如果忘记写 `&`,程序在运行到输入阶段时会直接崩溃!
**基础使用示例:**
```cpp
int age;
printf("请输入您的年龄:");
scanf("%d", &age); // 从键盘输入获取一个整数,存入 age 所在的内存地址
// 现在 age 中就储存了输入的数据
```
##### **`scanf` 的使用技巧**
1. **一次性读取多个数据**
```cpp
int a;
double b;
scanf("%d%lf", &a, &b); // 从键盘输入中读取一个整数和一个double类型的数据
```
*用户输入时用空格、Tab或回车 (空白字符) 隔开即可,`scanf` 会自动跳过它们。*
2. **易错点:不要在格式字符串里乱加标点,除非题目格式明确要求了**
* **错误写法**:`scanf("%d,%d", &a, &b);`
* **后果**:那么用户输入时**必须严格**按照格式输入:**[一个整数 逗号 一个整数]** 的格式,例如`5, 10` 。如果不带逗号输入`[5 10]`的话就会读取失败。
* **正确、安全的写法**:`scanf("%d%d", &a, &b);` 保持格式字符串的干净,只保留占位符。
---
#### **五、 实战演练**
##### **实战1:数字反转**
**解题思路**:我们不把 `123.4` 看作数字,而是看作“3个字符 + 1个小数点 + 1个字符”。利用 `scanf` 的格式匹配能力,将它们分离到不同的`char`变量中!
```cpp
#include <cstdio>
int main() {
char a, b, c, d;
// 输入格式为 %c%c%c.%c,匹配 [字符 字符 字符 小数点 字符] 的格式将4个字符分离出来
scanf("%c%c%c.%c", &a, &b, &c, &d);
// 按照 d.cba 的倒序格式输出
printf("%c.%c%c%c\n", d, c, b, a);
return 0;
}
```
*用 `scanf` 和 `printf`问题就会变得非常简单!*
##### **实战2:再分肥宅水(书本P23页)**
**题目要求**:$t$ 毫升水均分给 $n$ 名同学。输出每人获得多少毫升(严格保留3位小数)以及一共需要多少个杯子(每人2个)。
```cpp
#include <cstdio>
int main() {
double t;
int n;
// 用 %lf 读 double, 用 %d 读 int
scanf("%lf%d", &t, &n);
// t/n 对应 %.3f (保留三位小数), n*2 对应 %d,中间用 \n 换行
printf("%.3f\n%d\n", t / n, n * 2);
return 0;
}
```
---
#### **六、 总结**
* `cin/cout`:语法简单直观,能自动识别类型,是我们日常编程的常用选择。
* `scanf/printf`:
* **优点**:执行效率更高;拥有强大的**格式控制能力**,能实现精准的输入匹配和带精度的输出。
* **缺点**:语法稍显复杂,需要手动匹配占位符和变量类型,并且 `scanf` 必须带 `&`。
* **如何选择?** 在需要精确控制输入输出格式(如本讲的例题),就非常推荐使用 `scanf/printf` 。
@@ -0,0 +1,38 @@
### 参考答案
#### **一、 填空题**
1. `/ 10`
2. `45`
3. `cstdio`
4. `&`
5. `double`
6. `User ID: 99`
7. `%.1f`
8. `7`
9. `1`
10. `2`
#### **二、 单项选择题**
1. B
2. C
3. C
4. B (整数除法,结果是2)
5. B
6. C
7. B (`365/10` -> `36`, `36%10` -> `6`)
8. B
9. B
10. B (`8/3` 商2余2)
#### **三、 判断题**
1. × (反了,`/` 是除法,`%` 是取余)
2. √
3. × (不安全,用户必须严格输入 `10,20` 才能被读取,不通用)
4. √
5. × (必须包含 `<cstdio>`)
6. √
7. × (可以同时输出多个,如 `printf("%d %d", a, b);`)
8. √
@@ -0,0 +1,74 @@
## C++ 整数提取与格式化输入输出 课后习题
姓名: \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_
#### **一、 填空题**
1. C++ 中,获取一个整数个位数的“提取器”是 `% 10`,砍掉个位数的“削减器”是 \_\_\_\_\_\__\_\_\_\_。
2. 表达式 `456 % 10` 的计算结果是 `6`,表达式 `456 / 10` 的计算结果是 \_\_\_\_\_\_\_\_\_\_\_。
3. 要使用 `printf` 和 `scanf`,必须在代码顶部包含头文件 `#include <________________>`。
4. 在使用 `scanf` 读取数据时,必须在变量名前面加上符号 \_\_\_\_\_\_\_\_,它叫做取地址符。
5. 格式说明符 `%d` 用来对应 `int` 类型的整数,`%c` 用来对应 `char` 类型的字符,而 `%lf` 用来对应 \_\_\_\_\_\_\_\_ 类型的变量。
6. 阅读代码 `printf("User ID: %d", 99);`,它的输出结果是:\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_。
7. 如果想用 `printf` 输出一个浮点数,并严格保留 `1` 位小数,应该使用的格式说明符是 \_\_\_\_\_\_\_\_\_\_\_。
8. `int n = 87; printf("%d", n % 10);` 这段代码的输出结果是 \_\_\_\_\_\_\_\_\_\_\_。
9. `int n; scanf("%d", &n);` 如果用户输入 `123`,那么表达式 `n / 100` 的结果是 \_\_\_\_\_\_\_\_\_\_\_。
10. 表达式 `(528 / 10) % 10`它的计算结果是 \_\_\_\_\_\_\_\_\_\_\_。
#### **二、 单项选择题**
( ) 1. 为了获取整数 `921` 的个位数 `1`,应该使用哪个表达式?
A. `921 / 10` B. `921 % 10` C. `921 / 100` D. `921 % 100`
( ) 2. 下列哪条语句可以**正确**地用 `printf` 输出整数变量 `score` 的值?
A. `printf(score);` B. `printf("score");`
C. `printf("%d", score);` D. `printf("%d", &score);`
( ) 3. 下列哪条语句可以**正确**地用 `scanf` 读取一个整数并存入变量 `age` 中?
A. `scanf("%d", age);` B. `scanf("%c", &age);`
C. `scanf("%d", &age);` D. `scanf("%d", &age)`
( ) 4. `int a = 5, b = 2;`,`printf("结果是%d", a / b);` 的输出是?
A. `结果是2.5` B. `结果是2` C. `结果是%d` D. `结果是3`
( ) 5. `int n = 73; n = n / 10;` 执行后,`n` 的值变成了?
A. `73` B. `7` C. `3` D. `7.3`
( ) 6. 忘记在 `scanf` 的变量前加 `&` 符号,最可能导致什么后果?
A. 程序正常运行 B. 程序会卡住
C. 程序在运行时会崩溃或读入错误数据 D. 电脑会蓝屏
( ) 7. `int num; scanf("%d", &num);` 如果用户输入 `365`,那么 `printf("%d", (num/10)%10);` 会输出什么?
A. `3` B. `6` C. `5` D. `36`
( ) 8. 要输出一个浮点数并保留两位小数,应该用哪个格式说明符?
A. `%f` B. `%.2f` C. `%2f` D. `%d.2`
( ) 9. 拆分一个正整数 `n` 的所有位的通用步骤是?
A. 不断地:先用 `/ 10` 削减,再用 `% 10` 提取
B. 不断地:先用 `% 10` 提取,再用 `/ 10` 削减
C. 只需不断地 `/ 10`
D. 只需不断地 `% 10`
( ) 10. `int x=8, y=3; printf("%d %d", x/y, x%y);` 的输出结果是?
A. `2.66 2` B. `2 2` C. `3 2` D. `2 3`
#### **三、 判断题 (对的打“√”,错的打“×”)**
( ) 1. 运算符 `/` 是用来求余数的,运算符 `%` 是用来做除法的。
( ) 2. `printf` 中的占位符(如 `%d`)和后面的变量,它们的顺序和类型都必须一一对应。
( ) 3. `scanf("%d,%d", &a, &b);` 是一个安全的写法,用户输入 `10 20` 就能正确读取。
( ) 4. 对于任何正整数 `n`,`n / 10` 都能去掉它的个位数。
( ) 5. `printf` 和 `scanf` 都是 C++ 自带的核心功能,不需要包含任何头文件。
( ) 6. 整数 `5 % 10` 的结果是 `5`。
( ) 7. `printf` 只能输出一个变量,不能同时输出多个。
( ) 8. 拆分整数 `520` 时,`520 % 10` 的结果是 `0`。
@@ -0,0 +1,188 @@
### **C++ 顺序结构程序综合实战与解题方法 讲义**
#### **1. 引言 **
* **问题引入:我们学会了什么?我们要做什么?**
我们已经学会了如何定义变量、运算符和输入输出。已经可以写出一些基本的顺序结构程序了,我们现在要用这些工具,去综合利用解决一个实际问题。而很多同学在面对一个编程题时,会感觉大脑一片空白,不知道第一行代码该怎么写。这很正常!因为目前还缺少一套系统的解题流程。
* **价值阐述:为什么要学习解题流程?**
一个优秀的程序员,强大的不仅仅是他的代码能力,更是清晰的**逻辑思维和解决问题的能力**。今天要学习的这套流程,就是一个思维框架。它能帮助你:
1. **克服做题的恐惧**:面对任何题目,你都有一个可以遵循的“套路”,不会再手足无措。
2. **提高效率**:将一个大问题,分解成多个可控的小步骤,避免在错误的方向上浪费时间。
3. **提升正确率**:系统性地思考,减少逻辑漏洞。
---
#### **2. 顺序程序结构综合练习:如何交换两个变量的值**
* **问题:如何交换 num1 与 num2 变量里的值**:
```cpp
int num1 = 3, num2 = 4;
// ... 在这里写代码 ...
cout << num1 << " " << num2 << endl; // 目标:输出 4 3
```
* **错误的尝试**: 很多同学的第一反应是这样的:
```cpp
num2 = num1; // num2 的值变成了 3
num1 = num2; // num1 的值变成了 num2 (也就是3) 的值
```
**问题出在哪里?** 当你执行 `num2 = num1;` 时,`num2` 原本的值 `4` 就被 `num1` 的值 `3` **覆盖**掉了,永远地丢失了!就像你把一瓶可乐倒进了一瓶装有雪碧的瓶子里,雪碧就没了。
* **正确的解法:引入第三个“空杯子”**
为了不丢失任何一个值,我们需要一个临时的变量(我们称之为 `temp` 或 `num3`)来做中转。
**例:num1为可乐,num2为雪碧,尝试进行交换:**
1. `int temp = num1;` (把 num1 的可乐,倒进空杯子 temp 里)
2. `num1 = num2;` (把 num2 的雪碧,倒进 num1 杯里, num1 变成了雪碧)
3. `num2 = temp;` (把 temp 杯里的可乐,倒进 num2 杯里, num2 变成了可乐)
4. **至此,交换成功!**
* **代码实现**:
```cpp
int num1 = 3, num2 = 4;
int temp = num1; // 引入第三个变量
num1 = num2; num2 = temp; // 使用空杯子中转一下
cout << num1 << " " << num2; // 输出 4 3
```
---
#### **3. 编程解题的“七步法”**
现在,让我们以“**小鱼的游泳时间**”这个问题为案例,一步一步地走完我们解题的完整流程。
##### ==**第一步:读懂题目,明确题目要求“做什么”?**==
* **原文**:小鱼从 a 时 b 分一直游泳到当天的 c 时 d 分,计算它一共游了多少时间。
* **提炼任务**:核心任务是**计算时间差**。我们要用“结束时间”减去“开始时间”。
##### ==**第二步:理解输入,明确需要输入的原材料是什么?**==
* **原文**:输入四个整数 a, b, c, d。
* **解读**:程序需要从外界接收4个整数。我们必须定义4个 `int` 类型的变量来“接住”这些数据。
```cpp
int a, b, c, d;
cin >> a >> b >> c >> d;
```
* **重要误区**:绝对不能看到样例输入是 `12 50 19 10` 就在代码里写 `int a = 12;`!样例只是一个例子,我们的程序必须能处理任何合法的输入。**变量的值必须通过 `cin` 来获取!**
##### ==**第三步:思考解题逻辑,先想出解决问题的思路**==
在敲代码之前,先把思路理出来。清晰的逻辑思路,远比一开始就埋头敲错误的代码要高效得多。
* **实际的问题**:如何计算 `c时d分 - a时b分`?直接减很麻烦,比如 `19时10分 - 12时50分`,分钟不够减,需要向小时借位。
* **寻找更简单的方法 -> 统一单位**:
所有复杂的多单位计算,都可以通过**转换成统一的最小单位**来简化。这里的最小单位是“分钟”。
1. **将所有时间转换为分钟**:
* 开始时间(总分钟数)`start = a * 60 + b;`
* 结束时间(总分钟数)`end = c * 60 + d;`
2. **计算差值**:
* 现在游泳的总时长就是开始时间和结束时间的差值 `diff = end - start;`。
3. **将结果转换回目标格式**:
* 题目要求输出“e小时 f分钟”。我们手上有总分钟数,如何转换回去?
* 小时数 `e = diff_minutes / 60;` (利用整数除法自动取整)
* 分钟数 `f = diff_minutes % 60;` (利用取余运算得到不够1小时的剩余部分)
##### ==**第四步:把思路翻译为C++代码”**==
现在,我们把第三步的逻辑,一行行地用C++语言表达出来。
```cpp
// 步骤1:统一单位
int start = a * 60 + b;
int end = c * 60 + d;
int diff = ends - start;// 步骤2:计算差值
// 步骤3:转换格式
int e = diff / 60; // 小时
int f = diff % 60; // 分钟
```
##### ==**第五步:处理输出,保证格式绝对正确**==
* **原文**:一行内输出两个整数 e 和 f,用空格间隔。
* **解读**:在线评测系统(OJ)要求输出必须和标准答案一模一样,一个空格都不能差。
* **代码实现**:
```cpp
cout << e << " " << f;
```
##### ==**第六步:编译运行,检查语法错误**==
把所有代码组合起来,在你的编程环境中(如Dev-C++)按下编译运行键(F11)。
* 如果出现 `Compile Error (CE)`,仔细阅读编译器给出的错误信息,它会告诉你哪一行出错了,通常是漏了分号、括号不匹配、变量名写错等失误。
##### ==**第七步:样例测试,验证逻辑的正确性**==
* **操作**:程序运行后,输入题目给的样例 `12 50 19 10`,然后按回车。
* **比对**:
* 程序输出:`6 20` 并且题目的样例输出:`6 20`
* **结果完全一致!** 这说明我们的逻辑在处理这个样例时是正确的。
* **如果结果不一致怎么办? -> ==使用手动 cout 检查法==**
假设你的程序输出了奇怪的结果,比如 `1 -30`。这说明逻辑错了!
1. **手动在关键位置加入`cout`**:在你代码的关键步骤后,通过`cout`打印出关键的中间变量的值。
```cpp
int start = a * 60 + b;
cout << "开始总分钟: " << start << endl; // 实际输出出来看看 start 的值到底是多少,跟我想的是一致的吗
int end = c * 60 + d;
cout << "结束总分钟: " << end << endl; // 实际输出出来看看 end 的值到底是多少,跟我想的是一致的吗
int diff = end - start;
cout << "分钟差: " << diff << endl; // 实际输出出来看看最终的结果差的底是多少,跟我自己算出来的是一致的吗
```
2. **重新运行样例查看输出结果**:输入 `12 50 19 10`。
3. **进行核对**:
* 通过实际在草稿纸上计算:如果输入样例数据`12 50 19 10` 的话,那 `start`就应该是`12*60+50=770`,`end`应该是`19*60+10=1150`,`diff`应该是`380`。
* 查看你的程序输出,如果==某个`cout`打印的值和实际算出来不一致==,你就能知道问题出现在什么地方了!**就要仔细进行检查。**
---
#### **4. OJ的反馈结果 **
在我们的题目网站上递交你的代码后,最终它会给你一个结果来告诉我们你的代码是否正确。我们就要学会读懂OJ的反馈的结果。而系统的反馈主要有这几种:
#### **1. 正确`AC (Accepted)`**
* **含义**:**正确通过!**恭喜!意味着程序已经通过了所有测试数据。
#### **2. 编译错误:`CE (Compile Error)`**
* **含义**:**编译错误**。
* **解读**:这是最基础的错误。它意味着你的代码存在**语法问题**,翻译官根本无法读懂你的代码。
* **常见的编译错误原因**:
1. **漏写分号 (`;`)**:每一句指令的结束标志,就像中文的句号。
2. **括号不匹配**:`{}` 和 `()` 总是成双成对出现,少了一半就会出错。
3. **使用了中文标点**:代码世界里只认英文标点。中文的 `,;()` 都是非法字符。
4. **变量名拼错**:你定义时用的是 `score`,使用时却写成了 `scroe`。
5. **变量未定义就使用**:还没准备好盒子(声明变量),就想往里面放东西。
* **如何解决**:
`CE` 是最容易解决的问题。**在DevC++编程软件中仔细查看错误信息**,它通常会告诉你**哪一行**出错了,并给出一个英文的错误原因。根据提示回到你的代码中修改,直到在本地能够成功编译为止。
#### **3. 逻辑错误:`WA (Wrong Answer)`**
* **含义**:**答案错误**。`WA` 意味着你的**程序语法没问题**,也能顺利运行,但在某一组测试数据上,你的程序给出的输出结果和标准答案不一致。这说明,你的**程序设计本身存在逻辑漏洞**。
* **如何自查和更正?**:
1. **第一步:检查输出格式**
* 你的 `cout` 语句里是不是多了不该有的东西?比如 `cout << "答案是:" << sum;`。
* 你的输出里是不是少了题目要求的空格或换行?比如要求 `6 20`,你输出了 `620`。
2. **第二步:检查你的解题思路**
* 如果格式没问题,那一定是逻辑思路出了错。
* 拿出草稿纸,重新走一遍你的“七步做题法”中的第三步。你的思路真的能应对所有情况吗?是不是对题目的某个细节理解有偏差?
3. **第三步:使用 `cout` 手动检查法**
* 在代码的关键计算步骤之后,插入临时的 `cout` 语句,打印出中间变量的值进行检查。
* 用比如题目给出的样例来运行你的的程序。观察打印出来的中间值,和你在草稿纸上一步步推算的结果进行比对。一旦发现哪个变量的值与你的预期不符,就找到了程序“不正确的位置!就可以仔细进行检查并修正。
---
#### **6. 总结 **
**请务必牢记着七个编程的基本步骤**:
==**读懂题目**==(识别核心任务是什么) → ==**理解输入**== (明确输入数据的类型、数量、顺序及格式,并据此在程序中声明相应变量) → ==**思考逻辑**== (设计解决问题的思路) → ==**翻译代码**== (将逻辑思路翻译为具体的C++代码) → ==**处理输出**== (将答案根据题目要求的格式输出) → ==**编译查错**== (检查是否有语法错误) → ==**样例验证**== (使用样例数据对程序进行验证输出与样例输出是否一致)
养成**先动脑,后动手**的习惯。清晰的逻辑思路,远比一开始就埋头敲错误的代码要高效得多。
@@ -0,0 +1,35 @@
### **C++ 顺序结构综合练习 课后习题 - 答案**
#### **一、 填空题**
1. 思考解题逻辑
2. 第三个变量,`num1 = num2;`
3. 分钟
4. `diff / 60` , `diff % 60`
5. CE (Compile Error)
6. WA (Wrong Answer)
7. `cout`
#### **二、 单项选择题**
1. **D**. 这是错误的交换方法。`num1 = num2;` 后,`num1` 的值变为20。`num2 = num1;` 后,`num2` 的值也保持为20。
2. **C**. 样例不通过说明程序逻辑有问题,需要调试修正。
3. **B**. `小时数 * 60 + 分钟数` 是正确的换算逻辑。
4. **B**. 百分比要换算成小数,且结果可能为小数,应用 `double` 类型存储。
5. **C**. AC代表通过了所有测试,是最终的正确结果。
6. **C**. WA代表程序能运行但结果不对,这是逻辑或格式上的错误。CE才是语法错误。
7. **A**. `125 / 60` 整数除法得 `2`。`125 % 60` 取余数得 `5`。
8. **B**. 程序的价值在于处理不确定的、任意的合法输入,所以必须用 `cin`。
#### **三、 判断题**
1. √ (这是标准的三变量交换法。)
2. √ (讲义的核心思想之一,清晰的逻辑远比盲目试错重要。)
3. × (CE是编译错误,即语法错误。WA或TLE等才是逻辑算法错误。)
4. × (这种方法无法处理分钟不够减需要向小时借位的情况,统一单位是更简单可靠的方法。)
5. × (OJ系统会有更多、更复杂的测试数据,样例通过只是第一步。)
6. √ (对于评测系统来说,它只关心最终打印到屏幕上的字符序列是否完全匹配。)
7. √ (这是讲义中重点推荐的调试逻辑错误的方法。)
8. √ (因为 `* 0.2` 这类运算可能产生小数,用 `int` 会丢失精度。)
9. × (这行代码的作用是从键盘读取两个值,分别存入变量 `a` 和 `b`。)
10. √ (OJ是“死脑筋”的,格式必须完全一致。)
@@ -0,0 +1,78 @@
### **C++ 顺序结构设计综合练习 课后习题**
姓名: \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_
#### **一、 填空题**
1. 编程解题的“七步法”强调,在动手将思路翻译成代码之前,更重要的是先\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_。
2. 为了交换变量 `num1` 和 `num2` 的值,我们需要借助_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_。如果第一步是 `temp = num1;`,第三步是 `num2 = temp;`,那么中间的第二步应该是\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_。
3. 在解决“小鱼的游泳时间”问题时,为了简化计算,我们采用“统一单位”的方法,将“时”和“分”都统一成最小单位\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_。
4. 在解决“小鱼的游泳时间”问题时,在计算完毕小鱼从开始到结束的游泳时间 `diff` 分钟后,还需要将 `diff` 分钟的形式换算回小时和分钟,那么计算小鱼这天一共游的小时数的表达式为\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_;那么计算小鱼这天一共游的分钟数的表达式为\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_。
5. 如果在代码中漏写了分号或使用了中文标点,提交到OJ系统最可能收到的反馈是\_\_\_\_\_\_\_\_\_\_ (填写简称 CE/WA/AC)。
6. 如果程序的逻辑有漏洞,例如错把 `a > b` 写成了 `a < b`,导致计算结果错误,提交后最可能收到的反馈是\_\_\_\_\_\_\_\_\_\_\_\_\_\_ (填写简称CE/WA/AC)。
7. 当程序运行结果与预期不符时,可以在代码的关键位置加入临时的\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_语句来打印出中间变量的值,这种方法被称为“手动检查法”。
#### **二、 单项选择题**
( &nbsp; ) 1. 阅读以下代码,其最终输出是什么?
```cpp
int num1 = 10, num2 = 20;
num1 = num2;
num2 = num1;
cout << num1 << " " << num2;
```
​ A. 10 20 &emsp; B. 20 10 &emsp; C. 10 10 &emsp; D. 20 20
( &nbsp; ) 2. 根据编程解题“七步法”,当发现样例测试结果与预期不一致时,我们应该进入哪个环节?
A. 重新读题,理解要求
B. 检查输出格式
C. 使用“手动cout检查法”等手段,修复逻辑错误
D. 优化代码,提高运行速度
( &nbsp; ) 3. 对于“小鱼的游泳时间”问题,如果输入的开始时间是 `a` 时 `b` 分,那么将开始时间统一进制转换成分钟数的正确表达式是?
A. `a + b * 60` &emsp; B. `a * 60 + b` &emsp; C. `a * 60 + b * 60` &emsp; D. `(a + b) * 60`
( &nbsp; ) 4. 在“成绩计算”问题中,总成绩 `score = 作业(A)*20% + 小测(B)*30% + 期末(C)*50%`。以下哪段计算代码是正确的?
A. `int score = A * 20 + B * 30 + C * 50;`
B. `double score = A * 0.2 + B * 0.3 + C * 0.5;`
C. `int score = A * 0.2 + B * 0.3 + C * 0.5;`
D. `double score = A / 5 + B / 3 + C / 2;`
( &nbsp; ) 5. 在线评测系统(OJ)返回“Accepted (AC)”,这意味着什么?
A. 代码可以成功编译。
B. 代码通过了样例测试数据。
C. 代码通过了所有的测试数据,程序是完全正确的。
D. 代码的格式非常规范。
( &nbsp; ) 6. 某同学在提交代码后得到了“Wrong Answer (WA)”的反馈,有可能的原因是?
A. 代码中漏掉了一个分号`;`。
B. 变量名拼写错误。
C. 解题的逻辑思路存在问题,或者输出格式与要求不符。
D. 使用的变量太多,占用了过多内存。
( &nbsp; ) 7. 假设变量 `total_minutes` 的值为 `125`,执行以下代码后,输出是什么?
```cpp
int h = total_minutes / 60;
int m = total_minutes % 60;
cout << h << " " << m;
```
​ A. 2 5 &emsp; B. 2.08 5 &emsp; C. 2 15 &emsp; D. 2 25
( &nbsp; ) 8. “七步法”中“理解输入”这一步,下列说法正确的是什么?
A. 必须在代码中把变量赋值为样例输入的值,如 `int a = 12;`
B. 必须使用 `cin` 来从键盘获取不确定的输入值。
C. 必须给变量起一个和题目描述中一模一样的名字。
D. 必须一次性把所有需要的变量都在程序开头定义好。
#### **三、 判断题 (对的打“√”,错的打“×”)**
( &nbsp; ) 1. 交换两个变量 `a` 和 `b` 的值,代码 `int temp = a; a = b; b = temp;` 是正确的。
( &nbsp; ) 2. 在编程时,应该先思考好清晰的逻辑,再动手写代码,这样比直接埋头试错更高效。
( &nbsp; ) 3. 如果OJ返回 `Compile Error (CE)`,说明是程序的逻辑算法错了。
( &nbsp; ) 4. 在“小鱼的游泳时间”问题中,可以直接用结束的分钟减开始的分钟,小时减小时,不需要统一单位。
( &nbsp; ) 5. 一个程序在自己的电脑上用了一个样例测试通过了,那么提交到OJ就一定能获得 `AC`。
( &nbsp; ) 6. `cout << 6 << " " << 20;` 和 `cout << "6 20";` 对于OJ评测系统来说,输出结果是完全一样的。
( &nbsp; ) 7. “手动cout检查法”是定位逻辑错误的有效手段。
( &nbsp; ) 8. 在“成绩计算”问题中,因为成绩有小数,所以存储总分的变量最好声明为 `double` 类型。
( &nbsp; ) 9. `cin >> a >> b;` 这行代码的作用是,把 `a` 的值赋给 `b`。
( &nbsp; ) 10. OJ评测系统对输出格式要求极高,多一个或少一个空格都可能导致 `WA`。