• "蓝桥杯“基础练习:十六进制转八进制


    问题描述
      给定n个十六进制正整数,输出它们对应的八进制数。
    输入格式
      输入的第一行为一个正整数n (1<=n<=10)。
      接下来n行,每行一个由0~9、大写字母A~F组成的字符串,表示要转换的十六进制正整数,每个十六进制数长度不超过100000。
    输出格式
      输出n行,每行为输入对应的八进制正整数。
    注意
      输入的十六进制数不会有前导0,比如012A。
      输出的八进制数也不能有前导0。
    样例输入
    2
    39
    123ABC
    样例输出
    71
    4435274
    提示
      先将十六进制数转换成某进制数,再由某进制数转换成八进制。

    心得:

    题目有些难度,一开始想的是把16进制先转化为10进制,因为从10进制转化为8进制很容易。但是题目中输入的16进制位数规模大,不超过100000位,肯定不能化为10进制数。解法是先把16进制化为四个2进制数,然后三个二进制数一组再化为8进制。 注意 39(16进制)--〉0011    1001   (2进制) --〉111  001(8进制),是从二进制的低位开始三个一组来计算。

    代码:

    #include <iostream>
    #include <string.h>
    #include <stack>
    using namespace std;
    
    int fib(int n)//计算2的多少次方
    {
        int sum=1;
        if(n==0)
            return 1;
        else
        {
            for(int i=1;i<=n;i++)
                sum*=2;
            return sum;
        }
    }
    
    string str[11];
    
    int two[400008];//因为16进制的位数不超过100000,所以换成二进制数位数不超过400000
    
    int main()
    {
        int n,i,j,k;
        cin>>n;
        for(int k=1;k<=n;++k)
        {
            cin>>str[k];
            memset(two,0,sizeof(two));
            for( i=0;i<str[k].length();++i)//把十六进制的每一位变成4个二进制数,注意存放的顺序
            {
                if(str[k][i]>='0'&&str[k][i]<='9')
                {
                    int temp=str[k][i]-'0';
                    int tap=4*(i+1);//把two数组每4个元素为一组,连续,当前的十六进制位为two数组的最大下标+1
                    while(temp)
                    {
                        two[--tap]=temp%2;//首先要tap-1,因为two数组是从0开始的,这也解释了为什么上面说是最大下标+1
                        temp/=2;
                    }
                }
                else
                {
                    int temp=str[k][i]-55;//A-55得10
                    int tap=4*(i+1);
                    while(temp)
                    {
                        two[--tap]=temp%2;
                        temp/=2;
                    }
                }
            }//到目前为止把16进制转成了二进制
            int count=0;//二进制数三位一组来转化为8进制
            int sum=0;//连续三位二进制数的值
            stack<int>q;
            for(j=4*str[k].length()-1;j>=0;--j)//从two数组的存数的最大下标开始处理,每三个为一组,转化为8进制,保存在栈中
            {
                sum+=(two[j]*fib(count++));
                if(count==3)
                {
                    q.push(sum);
                    sum=0;
                    count=0;
                }
    
            }
            int sum1=0;//考虑处理的末尾,可能最后一组少于3个,有可能是一个,也可能是两个,单独处理,单独输出
            int c=0;
            for(int m=4*str[k].length()%3-1;m>=0;--m)//4*str[k].length()%3判断还剩下几个
            {
                sum1+=two[c++]*fib(m);
            }
            if(sum1!=0)
                cout<<sum1;//单独输出
            if(q.top()==0)
                q.pop();//去除前导0,如果有的话
            while(!q.empty())
            {
               cout<<q.top();//从栈中输出
                q.pop();
            }
            cout<<endl;
        }
        return 0;
    }
    

    运行:


    2014.3.4日修改

    上面写的代码太复杂了,看到同学写的该题,受到了启发。十六进制转二进制不用上面代码那么麻烦。

    另一种解法如下:

    #include <iostream>
    #include <string>
    using namespace std;
    
    int main()
    {
        int n;
        cin>>n;
        for(int k=1;k<=n;k++)
        {
            string s1,s2;//s1为输入的原始的十六进制串,s2为转化成的二进制串
            cin>>s1;
            s2="";//初始化
            for(int i=0;i<s1.length();i++)//遍历,字符串上加上每一位
            {
                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;
                }
            }
            int len=s2.length();
    
            if(len%3==1)//三个二进制为一位八进制,二进制串前面补0,确保二进制串的长度为3的倍数
                s2="00"+s2;
            else if(len%3==2)
                s2="0"+s2;
            int flag=0;
            for(int i=0;i<=s2.length()-3;i+=3)
            {
                int num=4*(s2[i]-'0')+2*(s2[i+1]-'0')+(s2[i+2]-'0');
                if(num)
                    flag=1;//忽略前导0
                if(flag)
                    cout<<num;
            }
            cout<<endl;
        }
        return 0;
    }


  • 相关阅读:
    java将string转化为int Yannis
    vm虚拟机启动报The VMware Authorization Service is not running错误 Yannis
    [org.hibernate.util.JDBCExceptionReporter] Cannot load JDBC driver class 'net. Yannis
    前台页面分页对总页数的判断 Yannis
    事务及其特性 Yannis
    iReport报表的简单函数及部分操作 Yannis
    spring aop与事务配置 Yannis
    大数据的验证和插入数据库 Yannis
    唔哇哈哈,拉霸机
    bindebug放到别的目录后不能看?编译器参数设置一下
  • 原文地址:https://www.cnblogs.com/sr1993/p/3697797.html
Copyright © 2020-2023  润新知