C++整数转成二进制方法总结

本文介绍了两种实用的二进制转换方法:一是通过位操作返回包含二进制数的vector,适用于固定位数的转换;二是使用递归输出任意位数的二进制数,灵活应对不同场景需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

经常遇到要用到二进制的情况,这里我就记录下

 

1.逐次经典位操作(返回一个含有二进制数的vector)

#include<iostream>
using namespace std;
#include<vector>
vector<int> Transform(int n)
{
    vector<int>m;
    for(int i =31; i>=0; i--)
    {
        m.push_back( ( (n>>i) & 1) );//与1做位操作,前面位数均为0
        //cout<<( (n>>i) & 1);//输出二进制
    }
    //cout<<endl;
    return m;
}

举例 若输入10;输出 00000000000000000000000000001010

 

2.利用递归输出,这里输出的是从1开始的位数,不一定是32位

#include<iostream>
using namespace std;
#include<vector>
//递归输出二进制函数
void BinaryRecursion(int n,vector<int>&ans)
{
    int a;
    a = n%2;
    n = n>>1;
    if (n != 0)
        BinaryRecursion(n,ans);
    //cout<<a;
    ans.push_back(a);
}

举例,若输入10,输出1010;

<think>我们首先需要理解八进制转二进制的基本原理:每个八进制数字对应3位二进制数。 例如: 八进制数 '7' 对应二进制 '111' 八进制数 '5' 对应二进制 '101' 因此,我们可以将输入的八进制字符串的每一位拆开,然后分别转换为3位二进制数(注意:如果转换后不足3位,需要在高位补0,但第一位如果不需要补0则可以不补,不过为了统一,我们可以从第一个非零位开始考虑,但通常我们会保留前导零直到整个数的开头。然而,题目要求是转换表示,所以我们可以按3位一组转换,然后拼接起来。但是注意,如果八进制数有多个数字,那么每个数字都对应3位,不能省略前导零(除了整个二进制数的前导零,但这里我们要求的是表示,所以通常保留转换后的所有位,因为八进制数的每一位都是独立的)。 然而,需要注意的是,如果八进制数有前导零(比如多位数的首位是0),那么转换后二进制数也会有前导零。但有时候我们可能希望去掉前导零,但题目没有明确要求,我们可以保留转换后的所有位(包括前导零),因为这样能准确反映八进制数的每一位。 但是,例如八进制数 "10" 转换为二进制: '1' -> "001" '0' -> "000" 拼接起来是 "001000",但这样会有多余的前导零。通常,我们可能会去掉整个二进制数前面的前导零,但是注意,八进制数中的0在中间是不能去掉的。所以,我们有两种做法: 1. 每一位都转换为3位二进制,然后直接拼接,这样可能会在开头有前导零(比如多位数的第一个数字是0或1等)。 2. 在转换后,将整个二进制字符串的前导零去掉,但要注意如果整个字符串都是0,那么要保留一个0。 不过,题目要求的是“表示”,所以我们可以选择保留每一位转换后的3位,这样能准确对应八进制数。但是,如果八进制数本身以0开头(比如"0123"),那么转换后的二进制数也会以0开头,这是允许的。但是,如果要去掉整个二进制数的前导零,那么需要小心:八进制数中间出现的0不能去掉。 因此,我们决定:将每一位八进制数字都转换为3位二进制数(包括前导零),然后拼接起来。但是,如果输入的八进制数包含小数点(题目没有提到,所以假设是整数),我们不考虑小数部分。另外,我们假设输入是有效的八进制字符串(只包含0-7)。 然而,我们也可以考虑在转换后去除最前面连续的0,但要注意如果整个数是0,那么应该输出一个0。但是,八进制数中如果第一位是0,那么转换后前面会有0,但八进制数本身允许前导零,所以二进制表示也应该有前导零。因此,我们可以不去除前导零,因为这是表示的要求。 但是,用户可能希望得到没有前导零的表示(除了0本身)。所以,我们可以提供一个选项,或者按照常规做法:在转换后去除最前面的连续0(但注意,如果去除后字符串为空,则输出0)。不过,题目没有明确要求,我们按照保留前导零的方式转换,然后让用户自行处理,或者我们提供一个去除前导零的版本。 考虑到要求,我们这里先按照每一位转换3位并拼接,然后去除整个字符串的前导零(但注意,如果八进制数就是0,那么转换后是000,去除后变成空,所以需要特殊处理:如果去除后为空,则输出0)。 步骤: 1. 输入一个八进制字符串(假设是整数,没有符号,没有其他字符)。 2. 遍历字符串的每个字符。 3. 将每个字符转换为对应的3位二进制字符串(使用一个映射表或者通过计算)。 4. 将所有的3位二进制字符串拼接起来。 5. 去除前导零(即找到第一个非零的位置,然后取子串;如果全零则输出一个0)。 但是,注意:如果八进制数只有一位,那么转换后就是3位,但我们可能希望去掉前导零?比如八进制数'1',转换后是"001",去掉前导零后变成"1"。这样更符合常规表示。 因此,我们决定在最后一步去除前导零。 另外,如果输入是空字符串,则返回空字符串。 映射表: '0' -> "000" '1' -> "001" '2' -> "010" '3' -> "011" '4' -> "100" '5' -> "101" '6' -> "110" '7' -> "111" 但是,我们也可以使用计算的方法:将字符转换为数字(0-7),然后分别除以4、2、1(即2^2, 2^1, 2^0)得到每一位。 例如:数字n,第一位:n/4,然后余数再除以2,最后一位是余数除以1。 不过,使用映射表更简单。 代码步骤: 1. 定义映射表:一个长度为8的字符串数组,下标0-7分别对应3位二进制字符串。 2. 遍历输入的八进制字符串的每个字符: 如果字符不是'0'~'7',则报错(这里简单处理,跳过或者返回错误,但题目假设有效,所以可以忽略,但最好检查)。 3. 将每个字符转换为数字,然后从映射表中取出对应的二进制字符串,拼接起来。 4. 拼接后,去除前导零:找到第一个非'0'的位置,如果没找到(即全0),则返回"0";否则返回从该位置开始的子串。 但是,注意:如果八进制数本身就是0(比如"0"),那么转换后是"000",去除前导零后变成空字符串,所以我们在去除前导零后,如果字符串为空,则返回"0"。 另外,如果八进制数有前导零(比如"00"),那么转换后是"000000",去除前导零后变成空,然后返回"0"。 因此,去除前导零的代码可以这样写: size_t start = 0; while (start < binaryStr.length() - 1 && binaryStr[start] == '0') { // 注意要留一个0,所以是到倒数第二个 start++; } binaryStr = binaryStr.substr(start); 但是这样写,如果整个字符串都是0,那么最后会剩下一个0吗?不会,因为当start指向最后一个字符时,如果最后一个字符是0,那么循环结束,然后取substr(start)就是"0"。但是,如果字符串是"000",那么start会指向最后一个0(即索引2),然后substr(2)得到"0"。所以这样写可以。 另一种写法:使用标准库的find_first_not_of,如果找不到非0字符,则返回0。 例如: size_t start = binaryStr.find_first_not_of('0'); if (start == string::npos) { binaryStr = "0"; } else { binaryStr = binaryStr.substr(start); } 这样更简洁。 现在,我们写代码: 注意:输入可能包含前导零,但我们在转换时,每一位都转换,所以会得到一串二进制字符串,然后去除整个字符串的前导零。 但是,如果八进制数有多个前导零,比如"000123",那么转换后会有9个0(因为每个0对应3个0,共3个0对应9个0),然后去除前导零后,剩下的就是"00000000123转换后的部分",但123转换后是001010011,所以整个字符串是000000001010011,去除前导零后是1010011?不对,应该是001010011(因为每一位都转换了,所以"000123"实际上是三个0和123,所以转换后是000000000001010011,然后去除前导零后是1010011?不对,123的转换是:1->001, 2->010, 3->011,所以拼接后是001010011,而前面的三个0转换后是000000000,所以整个字符串是000000000001010011,去除前导零后是1010011,但这样不对,因为123八进制对应的二进制应该是1010011吗?实际上八进制123等于二进制1010011(因为1*8^2 + 2*8^1 + 3*8^0 = 64+16+3=83,而1010011二进制是64+16+2+1=83,正确)。所以这个结果是正确的。 所以,我们按照上述步骤编写代码。 但是,如果用户输入的是空字符串,我们返回空字符串。 另外,我们也可以考虑使用标准库的字符串流,但这里我们直接处理字符串。 代码示例: 注意:我们假设输入字符串是有效的八进制数,不包含非法字符。 下面我们写一个函数,输入一个字符串(八进制表示),输出一个字符串(二进制表示,去除前导零)。</think>以下是将八进制数转换为二进制表示的C++代码示例及解析: ### C++代码实现 ```cpp #include <iostream> #include <string> #include <unordered_map> std::string octalToBinary(const std::string& octal) { // 八进制数字到二进制的映射表 static const std::unordered_map<char, std::string> octToBinMap = { {'0', "000"}, {'1', "001"}, {'2', "010"}, {'3', "011"}, {'4', "100"}, {'5', "101"}, {'6', "110"}, {'7', "111"} }; std::string binary; // 遍历八进制字符串的每个字符 for (char digit : octal) { auto it = octToBinMap.find(digit); if (it == octToBinMap.end()) { std::cerr << "错误:无效的八进制数字 '" << digit << "'\n"; return ""; } binary += it->second; // 拼接二进制字符串 } // 去除前导零(保留至少一个字符) size_t startPos = binary.find_first_not_of('0'); return (startPos == std::string::npos) ? "0" : binary.substr(startPos); } int main() { std::string octal; std::cout << "输入八进制数: "; std::cin >> octal; std::string binary = octalToBinary(octal); if (!binary.empty()) { std::cout << "二进制表示: " << binary << "\n"; } return 0; } ``` ### 关键逻辑解析 1. **映射关系** 每个八进制数字(0-7)对应3位二进制数: - $0 \to 000$ - $1 \to 001$ - $2 \to 010$ - $3 \to 011$ - $4 \to 100$ - $5 \to 101$ - $6 \to 110$ - $7 \to 111$ 2. **转换过程** - 遍历输入字符串的每个字符 - 通过查找表`octToBinMap`获取对应的3位二进制串 - 拼接所有二进制段(例如八进制`"53"` → `"101011"`) 3. **前导零处理** - 使用`find_first_not_of('0')`定位首个非零位 - 若全零则返回`"0"`(例如输入`"000"` → 输出`"0"`) ### 示例输入/输出 | 八进制输入 | 二进制输出 | |------------|------------| | `"7"` | `"111"` | | `"12"` | `"001010"` → `"1010"` | | `"345"` | `"11100101"` | ### 注意事项 1. **输入验证**:代码检测非法字符(如`'8'`、`'A'`)并报错 2. **效率**:时间复杂度为$O(n)$,其中$n$是八进制数的位数 3. **前导零**:最终输出会删除前导零以符合常规表示习惯
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值