酷代码 AI
菜单
服务商
DeepSeek字节豆包
更多选项

C++ 十进制转八进制与任意进制转换算法详解(无vector/oct版)

好的,我们来解决这两个非常经典的进制转换问题。这两个题目是递进关系,第一个是特定的十进制转八进制,第二个是通用的十进制转任意进制(M<=10)。 我将为你提供符合题目要求(**不使用 `vector`,不使用 `oct`**)的C++解法,并详细解释每一步的原理。 ## 🎯 题目一:P4038 十进制数转换成八进制 ### 问题分析 核心算法依然是“**除基取余法**”。我们用一个静态数组来存储每一位的余数,最后逆序输出。 ### 💻 代码实现 ```cpp #include <iostream> using namespace std; int main() { int decimal; cin >> decimal; // 边界情况:如果输入是0,直接输出0 if (decimal == 0) { cout << 0 << endl; return 0; } // 定义一个足够大的数组来存储余数 // 对于int范围(最多约21亿),八进制最多11位,这里取32绝对安全 int octal[32]; int index = 0; // 记录当前存储到了数组的哪个位置 // 除基取余法 while (decimal > 0) { octal[index] = decimal % 8; // 存储当前最低位 decimal /= 8; // 去掉最低位 index++; // 位置后移 } // 逆序输出数组中的有效元素 for (int i = index - 1; i >= 0; i--) { cout << octal[i]; } cout << endl; return 0; } ``` ### 📖 代码详解 1. **`int octal[32]`**: 静态数组,用于存储每一位的余数。`32` 的大小对于题目范围绰绰有余。 2. **`int index = 0`**: 这是一个“指针”变量,它始终指向数组中下一个空闲位置。循环结束后,`index` 的值就等于八进制数的位数。 3. **`while (decimal > 0)`**: 持续进行除基取余,直到十进制数变为 0。 4. **逆序输出**: 循环结束后,数组 `octal[0]` 存放的是最低位,`octal[index-1]` 存放的是最高位。所以我们需要从 `index-1` 循环到 `0` 来正确输出。 ## 🎯 题目二:P4039 进制转换 (通用版) ### 问题分析 这个题目是上一个题目的泛化。核心算法不变,只是除数从固定的 `8` 变成了用户输入的 `M`。 ### 💻 代码实现 ```cpp #include <iostream> using namespace std; int main() { int X, M; cin >> X >> M; // 边界情况:如果X是0,直接输出0(任何进制下,0都是0) if (X == 0) { cout << 0 << endl; return 0; } // 定义一个足够大的数组,注意这里是M进制 // 十进制数X最大为10^9,二进制需要的位数最多(约30位),这里取32位足够 int result[32]; int index = 0; // 除基取余法(基数是M) while (X > 0) { result[index] = X % M; // 存储余数 X /= M; // 更新商 index++; } // 逆序输出 for (int i = index - 1; i >= 0; i--) { cout << result[i]; } cout << endl; return 0; } ``` ### 📖 与第一题的区别 - **输入变量**:多读取了一个 `M`,表示目标进制。 - **运算操作**:`X % M` 和 `X /= M`,将固定的 `8` 替换为了变量 `M`。 - **数组命名**:为了通用性,将数组名从 `octal` 改为 `result`。 ## ✅ 开发建议与最佳实践 1. **先处理边界情况**:在进制转换中,`X = 0` 是一个非常重要的边界情况。如果不加处理,`while` 循环不会执行,程序将没有任何输出。 2. **数组大小选择**:`int` 类型最大值约 `2.1 * 10^9`,二进制表示需要 31 位。**数组大小设置为 32 或更多是绝对安全的**。不建议设得太小,以免大数输入时产生数组越界。 3. **代码重用性**:对于这类基础算法,可以封装成一个函数: ```cpp void convertToBase(int number, int base) { if (number == 0) { cout << 0; return; } int digits[32]; int len = 0; while (number > 0) { digits[len] = number % base; number /= base; len++; } for (int i = len - 1; i >= 0; i--) { cout << digits[i]; } } ``` 这样代码结构更清晰,也方便在其他地方调用。 ## 🚫 常见陷阱规避 - **忘记逆序**:新手最常见的错误。一定要记得从数组的最后一个有效元素开始输出。 - **循环条件**:使用 `while (X > 0)`,不要使用 `>= 0`,否则会陷入无限循环(因为 `X` 永远不会变为负数)。 - **M 的范围**:题目保证 `M <= 10`,这意味着所有余数都在 0-9 之间,可以直接输出。如果 `M > 10`,就需要用 `A, B, C...` 来表示大于 9 的余数了。 ## 🔧 扩展思考 - **如何处理 `M > 10` 的进制(如十六进制)?** 当余数大于 9 时,需要将其转换为字母 `A-F`。可以通过一个 `char` 数组或 `switch` 语句来实现映射。 - **如何处理负数的进制转换?** 这是一个更复杂的问题,通常涉及补码表示,不同的编程语言有不同的处理方式。对于竞赛题,一般默认输入为非负整数。 ######[AI写代码神器 | 1418点数解答 | 2026-07-22 09:39:05]

相关提问
本站限时免费提问中
实用工具查看更多
Linux在线手册 [开发类]
Jquery在线手册 [开发类]
今日油价 [生活类]
图片互转base64 [开发类]
时间转换器 [开发类]