版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/MM_GS/article/details/69486933
问题描述
给定n个十六进制正整数,输出它们对应的八进制数。
输入格式
输入的第一行为一个正整数n (1<=n<=10)。
接下来n行,每行一个由0~9、大写字母A~F组成的字符串,表示要转换的十六进制正整数,每个十六进制数长度不超过100000。
输出格式
输出n行,每行为输入对应的八进制正整数。
【注意】
输入的十六进制数不会有前导0,比如012A。
输出的八进制数也不能有前导0。
样例输入
2
39
123ABC
样例输出
71
4435274
【提示】
先将十六进制数转换成某进制数,再由某进制数转换成八进制。
思路:
先将十六进制数转换为二进制数,再以3位二进制数为一个整体转化为一个八进制数。
最初代码:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int n;
cin>>n;
string o[n],h[n];
for (int i=0;i<n;i++)
{
cin>>h[i];
}
for (int j=0;j<n;j++)
{
int lens=h[j].length();
string str=h[j];
string b[lens],b1[lens];
char a[lens];
int ha=lens/3;
int hb=lens%3;
for (int t=0;t<lens;t++)
{
a[t]=str[t];
}
for (int k=0;k<lens;k++)
{
switch (a[k])
{
case '0': b[k]="0000";break;
case '1': b[k]="0001";break;
case '2': b[k]="0010";break;
case '3': b[k]="0011";break;
case '4': b[k]="0100";break;
case '5': b[k]="0101";break;
case '6': b[k]="0110";break;
case '7': b[k]="0111";break;
case '8': b[k]="1000";break;
case '9': b[k]="1001";break;
case 'A': b[k]="1010";break;
case 'B': b[k]="1011";break;
case 'C': b[k]="1100";break;
case 'D': b[k]="1101";break;
case 'E': b[k]="1110";break;
case 'F': b[k]="1111";break;
}
}
string str1;
for (int n=0;n<lens;n++)
{
str1+=b[n];
}
int l=str1.length();
int m=0;
int hh=l/3+l%3;
string s[hh];
int t;
for (t=l-1;t>1;t=t-3)
{
s[m]+=str1[t-2];
s[m]+=str1[t-1];
s[m]+=str1[t];
m++;
}
if (t==1 || t==0)
{
m=m+1;
int t1=2-t;
if (t1=0)
{
s[m]="00";
s[m]+=str1[t];
}
if (t1=1)
{
s[m]="0";
s[m]+=str1[t-1];
s[m]+=str1[t];
}
}
char a1[m+1];
for (int kk=m;kk>-1;kk--)
{
if (s[kk]=="000")
{
if (kk=m)
;
else
a1[kk]='0';
}
if (s[kk]=="001")
a1[kk]='1';
if (s[kk]=="010")
a1[kk]='2';
if (s[kk]=="011")
a1[kk]='3';
if (s[kk]=="100")
a1[kk]='4';
if (s[kk]=="101")
a1[kk]='5';
if (s[kk]=="110")
a1[kk]='6';
if (s[kk]=="111")
a1[kk]='7';
}
string s2;
for (int ll=0;ll<m+1;ll++)
{
s2[ll]=a1[m-ll];
cout<<s2[ll];
}
cout<<s2<<endl;
}
return 0;
}
但是这个代码运行超时。
错误:二进制转八进制那里是将二进制全部转化完成存入字符串s2中,导致转化时的运行时间过长且占用空间太大。且代码太过繁杂。
成功代码:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int n;
cin>>n;
string h;
for (int i=0;i<n;i++)
{
cin>>h;
string s;
int lens=h.length();
for (int k=0;k<lens;k++)//十六进制转二进制
{
switch (h[k])
{
case '0': s+="0000";break;
case '1': s+="0001";break;
case '2': s+="0010";break;
case '3': s+="0011";break;
case '4': s+="0100";break;
case '5': s+="0101";break;
case '6': s+="0110";break;
case '7': s+="0111";break;
case '8': s+="1000";break;
case '9': s+="1001";break;
case 'A': s+="1010";break;
case 'B': s+="1011";break;
case 'C': s+="1100";break;
case 'D': s+="1101";break;
case 'E': s+="1110";break;
case 'F': s+="1111";break;
}
}
int lens2=s.length();
if (lens2%3==1) //lens2判断是否为3的倍数,不是则s前面补0
{
s="00"+s;
}
else if(lens2%3==2)
{
s="0"+s;
}
int flag=0;//判断八进制数的首位是否为零
for (int j=0;j<lens2;j+=3)//三位二进制转为一位八进制
{
int num=4*(s[j]-'0')+2*(s[j+1]-'0')+(s[j+2]-'0');
if (num)
{
flag=1;
}
if (flag)
{
cout<<num;
}
}
cout<<endl;
}
return 0;
}
改正后的代码,修改了许多不必要的繁杂,将十六转二的字符串链接直接在switch函数中完成,用二进制的字符串长度对3求余来判断是否在二进制字符串前面加0。用flag判断八进制的首位是否为零。以三位二进制为一个集合转化为八进制并且直接输出,避免了整个八进制存入数组或string字符串中。
菜鸟一枚,不太会用文字描述。