问题描述
给定n个十六进制正整数,输出它们对应的八进制数。
输入格式
输入的第一行为一个正整数n (1<=n<=10)。
接下来n行,每行一个由0~9、大写字母A~F组成的字符串,表示要转换的十六进制正整数,每个十六进制数长度不超过100000。
输出格式
输出n行,每行为输入对应的八进制正整数。
【注意】
输入的十六进制数不会有前导0,比如012A。
输出的八进制数也不能有前导0。
样例输入
2
39
123ABC
样例输出
71
4435274
【提示】
先将十六进制数转换成某进制数,再由某进制数转换成八进制。
题目提示了使用一种进制作为中转,很容易想到先转为十进制,然后再转为八进制,但是要注意的是,当十六进制数很大时,转为十进制时使用的整数类型会无法存储下这么大的数,所以正确的做法应该是先转为二进制,然后再转为八进制。
#include<iostream>
using namespace std;
#include<math.h>
int* num1; //存储二进制
int* num2; //存储八进制
int charToint(char c)
{
if(c>='0'&&c<='9')return c-'0';
return 10+c-'A';
}
//十六进制转二进制
int shiliuToer(string s)
{
int n=s.length();
for(int i=0;i<n;i++)
{
int x=charToint(s[i]);
for(int j=3;j>=0;j--)
{
num1[i*4+j]=x%2;
x=x/2;
}
}
//去除前导0
int i=0;
while(i<4*n&&num1[i]==0)
{
i++;
}
num1=num1+i;
return 4*n-i;
}
//二进制转八进制
int erToba(int n)
{
int i=n-1;
int count=0;
int a,b,c;
while(i>=0)
{
a=num1[i--];
if(i>=0)b=num1[i--];
else b=0;
if(i>=0)c=num1[i--];
else c=0;
num2[count++]=a+b*2+c*4;
}
return count;
}
int main()
{
int n;
cin>>n;
num1=new int[500000]; //十进制
num2=new int[500000]; //八进制
string s;
for(int i=0;i<n;i++)
{
cin>>s;
if(s=="0")
{
cout<<0<<endl;
continue;
}
int n1=shiliuToer(s); //十六进制转成二进制
int n2=erToba(n1); //二进制转成八进制
for(int j=n2-1;j>=0;j--)
{
cout<<num2[j];
}
cout<<endl;
}
return 0;
}