Files

169 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## **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`)。