十六进制转八进制(浅显易懂)

十六进制转八进制

#分析+算法实现+代码+测试数据
#技巧:分析+处理+调试(大不了就调试)

分析

这个题是蓝桥杯的一道练习题,对于十六进制转八进制的话,是可以通用的。
题目的描述大概是这样的:给n个十六进制数,n<=10,每个数的长度不超过10000。

这里涉及到字符型以及string类类类型,待会再强调。


下面分析一下此题:
要想把十六进制转成八进制,首先想到把十六进制转成二进制再转成八进制。
于是,如何把十六进制数转化成二进制01呢?首先想到的是偷懒,直接利用
c语言的scanf和printf类型转换,真特么容易!

哦,差点忘掉了,每个十六进制数的长度不超过一万!其实,我看到这里就
呵呵了,不是我不会,是懒的写,字符串的一些操作太繁琐,有些细节还要
耐心的处理,很容易就把一个人清晰的脑袋拧成一股麻绳,各种自我质疑,
不过不要着急,所以保持冷静,这种题还是很容易的,相信自己。
经过分析,这道题的算法倒是很容易,如下:

每一个十六进制的值都可以转化成4位二进制值,每三个二进制值组成一个八进制值,所以,先把十六进制转换成01的二进制字串,然后把01串转化成八进制。


算法实现

因为十六进制总共就十六个字符,这里使用switch对应01码进行选择,然后对string对象str作+运算,逐个转换成4位的01码存入到string的对象str中,直到全部转化成二进制代码。

然后把二进制字串的长度*4%3求出存入一个变量r中。
如何求string类类型的长度呢?
1 str.length();
2 str.size();

接着有一个优化技巧可以使用,(优化技巧)就是这个
01串开始转化八进制的时候该从哪开始?
如果余数为零,对谁取余从谁开始,否则从余数开始。

这个是我对代码进行优化后发现的。

然后就是如何转化成八进制的整数输出呢?当然是看01码了。因为每三位一组成一个八进制值,使用一个变量ans记录在三位中的哪个位上,使用sum+=pow(2,ans)转化成数值,每执行完一组,ans和sum归初值。每次输出sum值,最终输出的就是目标的八进制。

因为是多组输入数据,而只定义了两个string的对象对整个程序进行操作,所以
string类类型的对象如何清零呢?
1 str.clear()//使用clear()函数;
2 str="";//赋空

小插曲(可以不看,为了拧回博主的脑回路而写)

之前我常常会把string类类型char型混用,如今我终于弄明白了。

比如:
之前我会这样写,scanf输出string类型的对象值。
string str;printf("%s",str);
哎?为什么会报错?

或者说会写成这样,使用c的函数企图得到string型对象的长度。
string str; int len=strlen(str);

后来的后来,我终于明白了,之前学习c的时候顺带学的c++,我一直把这string 和 char型的东西当成一家的,其实,他们只是有关系,但是不是一家的,东西也不能乱串使用,string是字符串类类型。

(这里我使的是string类型的对象对字符串进行操作。)

代码

//利用switch+string类型
//注意字符串要双引号

#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<math.h>
using namespace std;
int main(){
    int n;
    string str_temp,str_in;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        str_in="";
        str_temp="";//给字符串赋空

        cin>>str_in;
        int len=str_in.length();

        for(int j=0;j<len;j++){
            switch(str_in[j]){
                case '0': str_temp+="0000";break;
                case '1': str_temp+="0001";break;
                case '2': str_temp+="0010";break;
                case '3': str_temp+="0011";break;
                case '4': str_temp+="0100";break;
                case '5': str_temp+="0101";break;
                case '6': str_temp+="0110";break;
                case '7': str_temp+="0111";break;
                case '8': str_temp+="1000";break;
                case '9': str_temp+="1001";break;
                case 'A': str_temp+="1010";break;
                case 'B': str_temp+="1011";break;
                case 'C': str_temp+="1100";break;
                case 'D': str_temp+="1101";break;
                case 'E': str_temp+="1110";break;
                case 'F': str_temp+="1111";break;
                default: break;
            }
        }
        //cout<<str_temp<<endl;
        //把01串转化成目标串
        int len_s=str_temp.length();
        int ans=2;
        int sum=0;
        int r=len*4%3;

        if(r==1){
            if(str_temp[0]=='1')
                printf("1");
        }
        else if(r==2){
            if(str_temp[0]=='0'&&str_temp[1]=='1')
                printf("1");
            else if(str_temp[0]=='1'&&str_temp[1]=='0')
                printf("2");
            else if(str_temp[0]=='1'&&str_temp[1]=='1')
                printf("3");
        }
        else{
            if(str_temp[0]=='0'&&str_temp[1]=='0'&&str_temp[2]=='0')
                r=3;
        }

        for(int i=r;i<len_s;i++)
            {
                if(str_temp[i]=='1')
                    sum+=pow(2,ans);
                ans--;
                if(ans==-1)
                {
                    printf("%d",sum);
                    ans=2;
                    sum=0;
                }
            }
        printf("\n");
    }
}

测试数据

输入
2
39
123ABC

输出
71
4435274

评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值