284 lines
7.4 KiB
Markdown
284 lines
7.4 KiB
Markdown
# 第4课:数据类型、ASCII码与分支结构
|
||
|
||
## 教学目标
|
||
- 掌握五种常用数据类型:int、char、double、bool、string
|
||
- 理解 char 的 ASCII 码本质
|
||
- 能用 ASCII 码判断和转换字符类型
|
||
- 掌握 double 的格式化输出
|
||
- 掌握输入输出、算术/关系/逻辑运算与类型转换
|
||
- 掌握 if、else if、else、switch 和三目运算
|
||
- 掌握普通打擂台与带并列规则的二次打擂台
|
||
|
||
## 核心考点:数据类型、类型转换与数据范围
|
||
|
||
### 考什么
|
||
考试会要求判断变量应使用哪种类型、计算表达式结果、完成字符与整数转换,或分析整数溢出和小数精度。真正的重点是:数据以什么形式存储,会直接影响运算结果。
|
||
|
||
### 必须理解
|
||
`int` 存整数,范围有限;较大的整数应使用 `long long`。`double` 存小数,但可能存在微小精度误差。`char` 表面是字符,内部保存对应的 ASCII 整数,因此 `'7' - '0'` 得到整数 7。两个整数相除仍做整数除法,小数部分会被截掉;只要一边先转成 `double`,才会保留小数。赋值或运算时发生类型转换,可能扩大范围,也可能丢失信息。
|
||
|
||
### 核心写法
|
||
```cpp
|
||
double average = 1.0 * sum / n; // 先变成浮点运算
|
||
int digit = c - '0'; // 数字字符转整数
|
||
char c = digit + '0'; // 0~9 转数字字符
|
||
long long product = 1LL * a * b;
|
||
```
|
||
`1.0` 触发浮点运算,`1LL` 让乘法从一开始就在 `long long` 范围内进行。
|
||
|
||
### 常见错误
|
||
- `double average = sum / n;` 中右边先做整数除法,赋给 double 时小数已经丢失。
|
||
- 把字符 `'5'` 当成整数 5;它们的存储值不同。
|
||
- 结果变量使用 `long long`,但 `a * b` 已先按 int 溢出。
|
||
- 用 `==` 直接比较复杂浮点计算结果,忽略精度误差。
|
||
|
||
### 判断是否掌握
|
||
能根据数据范围选择 `int`、`long long` 或 `double`,能手算整数除法与类型转换结果,并能完成数字字符和整数之间的转换。
|
||
|
||
---
|
||
|
||
## 一级、二级核心:运算、转换与分支
|
||
|
||
### 输入输出与运算符
|
||
|
||
一级要求熟练使用 `cin`、`cout`,掌握算术、关系和逻辑运算:
|
||
|
||
```cpp
|
||
int a, b;
|
||
cin >> a >> b;
|
||
cout << a + b << endl;
|
||
|
||
bool valid = (a >= 0 && a <= 100);
|
||
```
|
||
|
||
整数除法会丢弃小数部分;需要小数时,应让至少一个运算数先转成 `double`。
|
||
|
||
### 隐式转换与强制转换
|
||
|
||
```cpp
|
||
double average = 1.0 * sum / count; // 隐式转换为 double
|
||
int code = (int)letter; // 强制转换为 int
|
||
char letter = (char)code; // 强制转换为 char
|
||
```
|
||
|
||
类型范围变大通常较安全;从浮点数转成整数会丢弃小数部分。
|
||
|
||
### 多层分支
|
||
|
||
```cpp
|
||
if (score >= 90) {
|
||
cout << "A";
|
||
} else if (score >= 80) {
|
||
cout << "B";
|
||
} else if (score >= 60) {
|
||
cout << "C";
|
||
} else {
|
||
cout << "D";
|
||
}
|
||
```
|
||
|
||
多个条件互斥时使用 `else if`,避免多个独立 `if` 重复执行。
|
||
|
||
### `switch` 语句
|
||
|
||
```cpp
|
||
switch (choice) {
|
||
case 1: cout << "加法"; break;
|
||
case 2: cout << "减法"; break;
|
||
default: cout << "无效选择";
|
||
}
|
||
```
|
||
|
||
`switch` 适合根据一个整数或字符的不同取值进行分支。每个 `case` 后通常需要 `break`,否则会继续执行后面的分支。
|
||
|
||
### 三目运算
|
||
|
||
```cpp
|
||
int bigger = (a > b) ? a : b;
|
||
```
|
||
|
||
三目运算适合简单的二选一,不适合代替复杂的多层分支。
|
||
|
||
### 打擂台与二次规则
|
||
|
||
寻找最接近目标值的数时,先比较距离;距离相同再比较数值:
|
||
|
||
```cpp
|
||
if (abs(x - target) < abs(best - target) ||
|
||
(abs(x - target) == abs(best - target) && x < best)) {
|
||
best = x;
|
||
}
|
||
```
|
||
|
||
擂主必须用第一个合法候选值初始化,不能随意设为 0。
|
||
|
||
## 题目一:判断字符类型并输出ASCII码
|
||
|
||
### 核心代码(一句话)
|
||
> 字符类型判断的核心:**char 本质是整数(ASCII码),可以在字符范围和整数之间自由比较和转换。**
|
||
|
||
### 自然语言思路
|
||
键盘上敲的每个字符,在计算机里都存成了一个整数——这就是 **ASCII 码**。
|
||
|
||
记住三个关键 ASCII 码:
|
||
- `'0'` = 48,`'1'`~`'9'` 依次递增
|
||
- `'A'` = 65,`'B'`~`'Z'` 依次递增
|
||
- `'a'` = 97,`'b'`~`'z'` 依次递增
|
||
|
||
所以判断一个字符是什么类型,有两种方法:
|
||
|
||
**方法一(看 ASCII 码范围)**:
|
||
- 如果 `c` 在 `'A'` ~ `'Z'` 之间(即 65~90)→ 大写字母
|
||
- 如果 `c` 在 `'a'` ~ `'z'` 之间(即 97~122)→ 小写字母
|
||
- 如果 `c` 在 `'0'` ~ `'9'` 之间(即 48~57)→ 数字
|
||
- 否则 → 其他字符
|
||
|
||
**方法二(用第1课学的自带函数)**:
|
||
- `isupper(c)` → 大写字母
|
||
- `islower(c)` → 小写字母
|
||
- `isdigit(c)` → 数字
|
||
|
||
最后,`int(c)` 或 `(int)c` 直接输出字符对应的 ASCII 码值。
|
||
|
||
### 伪代码
|
||
```
|
||
输入字符 ch
|
||
|
||
如果 ch 在 'A' ~ 'Z' 之间:
|
||
输出 "大写字母"
|
||
否则如果 ch 在 'a' ~ 'z' 之间:
|
||
输出 "小写字母"
|
||
否则如果 ch 在 '0' ~ '9' 之间:
|
||
输出 "数字"
|
||
否则:
|
||
输出 "其他字符"
|
||
|
||
输出 "ASCII码 = " + int(ch)
|
||
```
|
||
|
||
### 真实代码
|
||
```cpp
|
||
#include <iostream>
|
||
#include <cctype> // isupper、islower、isdigit
|
||
using namespace std;
|
||
|
||
int main() {
|
||
char ch;
|
||
cin >> ch;
|
||
|
||
// 方法一:ASCII 码范围判断
|
||
if (ch >= 'A' && ch <= 'Z') {
|
||
cout << "大写字母" << endl;
|
||
} else if (ch >= 'a' && ch <= 'z') {
|
||
cout << "小写字母" << endl;
|
||
} else if (ch >= '0' && ch <= '9') {
|
||
cout << "数字" << endl;
|
||
} else {
|
||
cout << "其他字符" << endl;
|
||
}
|
||
|
||
// 输出 ASCII 码值
|
||
cout << "ASCII码 = " << (int)ch << endl;
|
||
|
||
return 0;
|
||
}
|
||
```
|
||
|
||
### 方法二(用自带函数,更简洁)
|
||
```cpp
|
||
if (isupper(ch)) {
|
||
cout << "大写字母" << endl;
|
||
} else if (islower(ch)) {
|
||
cout << "小写字母" << endl;
|
||
} else if (isdigit(ch)) {
|
||
cout << "数字" << endl;
|
||
} else {
|
||
cout << "其他字符" << endl;
|
||
}
|
||
```
|
||
|
||
### 注意点
|
||
1. **`char` 能直接比大小**:`ch >= 'A'` 就是在比较 ASCII 码值,不需要先转成 int。
|
||
2. **字符写单引号**:`'A'` 不是 `"A"`,单引号是 char,双引号是字符串。
|
||
3. **ASCII 码值记忆技巧**:`'0'`=48,`'A'`=65,`'a'`=97。小写字母 = 大写字母 + 32。
|
||
4. **大小写互转**:大写转小写 `ch + 32`,小写转大写 `ch - 32`。或者用 `tolower(ch)` / `toupper(ch)`(返回 int,需要转回 char)。
|
||
5. **不要混用 string 和 char**:`string` 是字符串(双引号),`char` 是单个字符(单引号),两者不同。
|
||
|
||
---
|
||
|
||
## 题目二:(待橙子补充)
|
||
|
||
> 建议覆盖:double 格式化输出、int vs long long 范围等
|
||
|
||
---
|
||
|
||
### 核心代码(一句话)
|
||
>
|
||
|
||
### 自然语言思路
|
||
|
||
|
||
### 伪代码
|
||
|
||
|
||
### 真实代码
|
||
```cpp
|
||
|
||
```
|
||
|
||
### 注意点
|
||
|
||
|
||
---
|
||
|
||
## 题目三:(待橙子补充)
|
||
|
||
> 建议覆盖:bool 类型、string 基本操作等
|
||
|
||
---
|
||
|
||
### 核心代码(一句话)
|
||
>
|
||
|
||
### 自然语言思路
|
||
|
||
|
||
### 伪代码
|
||
|
||
|
||
### 真实代码
|
||
```cpp
|
||
|
||
```
|
||
|
||
### 注意点
|
||
|
||
|
||
---
|
||
|
||
## 本课打油诗
|
||
|
||
> int 存整数范围广,char 单字符本质藏。
|
||
> double 小数保精度,bool 对错分两旁。
|
||
> string 处理字符串,五种类型记心上。
|
||
|
||
---
|
||
|
||
## ASCII 码速查表(常用)
|
||
|
||
| 字符 | ASCII 码 |
|
||
|------|----------|
|
||
| `'0'` ~ `'9'` | 48 ~ 57 |
|
||
| `'A'` ~ `'Z'` | 65 ~ 90 |
|
||
| `'a'` ~ `'z'` | 97 ~ 122 |
|
||
| 空格 `' '` | 32 |
|
||
|
||
> 记忆口诀:**4A = 65**,不是"4个A",是"数字4开头,A是65"。小写比大写多32。
|
||
|
||
---
|
||
|
||
## 课后作业
|
||
(待补充)
|
||
1.
|
||
2.
|