您的位置:首页 > 其它

再理解:十六进制转八进制

2018-03-05 15:32 253 查看
本题来源于蓝桥杯:

问题描述

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

输入格式

  输入的第一行为一个正整数n (1<=n<=10)。

  接下来n行,每行一个由0~9、大写字母A~F组成的字符串,表示要转换的十六进制正整数,每个十六进制数长度不超过100000。

输出格式

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

注意

  输入的十六进制数不会有前导0,比如012A。

  输出的八进制数也不能有前导0。

样例输入

2

39

123ABC

样例输出

71

4435274

提示

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

AC代码:(此代码为摘录)

#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;
}


对题目和代码的深入理解:

(我提倡在看到一个问题后,先不要急于敲代码,而是在脑中或者练习纸上把整个题目的框架过一遍,然后在迅速的写代码。其中要考虑的是:1、策略 2、结构3、更适用的算法。)

1、题目要求是十六进制转八进制,根据进制之间的转换规律,先把十六进制转换成二进制,然后在把二进制转化成八进制,这是这个题的总的思想。

2、然后在考虑细节的用法。对于十六进制的输入我们该怎么做选择?我们知道十六进制的输入可以是这样的:

int num;
scanf("%o",&num);


我们也可以通过把十六进制看成一个字符串来对待。说到字符串,C++中有特别好用的string类函数,可以轻易的帮我们这个忙。所以这么看了来,我们就大可以选择string类的字符串了。

3、此时我们心里就一定要开始去考虑整个代码怎么去构建了。

第一步是把十六进制转化为二进制。

第二步就是想怎么把二进制转化为八进制。(要考虑可实行性,可以多考虑几个方法,取最优)

小提示:写代码前最好是给自己的思路和整体的实现方法评个估,哪里是模糊不清的,哪里是不可实现的,等等。不要等到真正要写代码了,写到那个地方了,不知道怎么实现,或者上下的整体不对称,上面的结构不符合下面的实现方法,这样整个代码就作废了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  十六进制 八进制