十六进制转八进制

十六进制转八进制

1.问题详情

问题描述
  给定n个十六进制正整数,输出它们对应的八进制数。

输入格式
  输入的第一行为一个正整数n (1<=n<=10)。
  接下来n行,每行一个由09、大写字母AF组成的字符串,表示要转换的十六进制正整数,每个十六进制数长度不超过100000。

输出格式
  输出n行,每行为输入对应的八进制正整数。

【注意
  输入的十六进制数不会有前导0,比如012A。
  输出的八进制数也不能有前导0。

样例输入
  2
  39
  123ABC

样例输出
  71
  4435274

【提示
  先将十六进制数转换成某进制数,再由某进制数转换成八进制。

2.解题思路

​ 这道题提示了先转化成某进制,我一开始就会想到转换成十进制,但后来我发现某些测试用例的十六进制数的长度太长,转化为十进制后连long long都容不下,所以就转换思路,将其转换为二进制,发现如果十六进制数长度最长为100000,二进制长度也就400000,并且可以用三个string字符串来存储一个数的十六进制,二进制以及八进制。

3.解题代码

#include<iostream>
#include<string>
using namespace std;
int main(){
    int n;//输入的16进制数的个数
    string s1,s2,s3;//s1为输入的十六进制串,s2为转化的二进制串,s3为八进制字符串
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>s1;
        s2="";//初始化s2
        for(int i=0;i<s1.length();i++){//string字符串高位字符存在低位地址,故可以从下标0开始遍历字符串s1将其转化为s2
            switch(s1[i]){
              case '0':s2+="0000";break;
              case '1':s2+="0001";break;
              case '2':s2+="0010";break;
              case '3':s2+="0011";break;
              case '4':s2+="0100";break;
              case '5':s2+="0101";break;
              case '6':s2+="0110";break;
              case '7':s2+="0111";break;
              case '8':s2+="1000";break;
              case '9':s2+="1001";break;
              case 'A':s2+="1010";break;
              case 'B':s2+="1011";break;
              case 'C':s2+="1100";break;
              case 'D':s2+="1101";break;
              case 'E':s2+="1110";break;
              case 'F':s2+="1111";break;
              default:break;
            }
        }
        s3="";//初始化s3
        int j=0,k;
        while(s2[j]=='0'){//找到第一个不是字符‘0’的位置,使转化的八进制没有前导0
            j++;
        }

        for(k=s2.length()-3;k>=j;k=k-3){//从低位字符开始转化,即从高位地址开始,初始值k要减3是因为要截取其后的3个二进制数
              string s="";//临时存储截取的字符串
              s=s2.substr(k,3);
              if(s=="000")
                s3+="0";
              else if(s=="001")
                s3+="1";
              else if(s=="010")
                s3+="2";
              else if(s=="011")
                s3+="3";
              else if(s=="100")
                s3+="4";
              else if(s=="101")
                s3+="5";
              else if(s=="110")
                s3+="6";
              else if(s=="111")
                s3+="7";
        }

        if(k==j-1){//如果k等于j-1,说明高位字符还有两个二进制数没有转化为八进制,由于去掉了前导0,从j开始的两个二进制数只能是"10"或"11"
            string s=s2.substr(k+1,2);
  
            if(s=="10")
                s3+="2";
            else
                s3+="3";
        }
        if(k==j-2){//如果k等于j-2,说明高位字符有一个二进制数没有转化为八进制,由于去掉了前导0,从j开始的一个二进制数只能是"1"
            string s=s2.substr(k+2,1);
            if(s=="1")
            s3+="1";
        }
        for(int i=s3.length()-1;i>=0;i--)//由于转化时s2的低位字符转化到了s3的高位字符,故需要倒序输出正确结果
        cout<<s3[i];
        cout<<endl;
    }
   return 0;
}

​ 需要注意的是二进制在转化为八进制时要把二进制的前导0去掉,而且若是二进制的位数不是3的倍数时,要将剩下的2个或1个二进制位数转化为八进数。

4.运行结果

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值