題目鏈接:Click here here
基礎練習 十六進制轉八進制
時間限制:1.0s 內存限制:512.0MB
問題描述
給定n個十六進制正整數,輸出它們對應的八進制數。
輸入格式
輸入的第一行爲一個正整數n (1<=n<=10)。
接下來n行,每行一個由0~9、大寫字母A~F組成的字符串,表示要轉換的十六進制正整數,每個十六進制數長度不超過100000。
輸出格式
輸出n行,每行爲輸入對應的八進制正整數。
【注意】
輸入的十六進制數不會有前導0,比如012A。
輸出的八進制數也不能有前導0。
樣例輸入
2
39
123ABC
樣例輸出
71
4435274
【提示】
先將十六進制數轉換成某進制數,再由某進制數轉換成八進制。
思路:先將十六進制轉換成二進制,再轉換成八進制。
一位十六進制位對應四位二進制位,三位二進制位對應一位八進制位。
輸入的十六進制用字符型,字符串輸入哦;由於一個十六進制位依次對2取餘,得到的第一個餘數在最右邊,最後一個餘數在最左邊,所以可以採用倒序轉換的方法。這樣依次取得的餘數正序存儲到二進制數組中。二進制數組可採用整型或字符型。
十六進制轉換成二進制的代碼如下:
int j,k=0,i;
for(i=len1-1;i>=0;i--)//倒序,得到十六進制對應的二進制數組
{
j=4;
int flag;
if(strD[i]>='0'&&strD[i]<='9')
flag=strD[i]-'0';
else if(strD[i]>='A'&&strD[i]<='Z')
flag=strD[i]-'A'+10;
while(j--) //一位十六進制對應四位二進制,連除四次,保留餘數
{
strB[k++]=(flag%2)+'0';
flag>>=1;
}
}
正常的順序中二進制轉換成八進制是左邊最高位乘以4,右邊最低位乘以1,,倒序存儲時,左側最高位乘以1,右側最低位乘以4。
法一:
正序轉換,倒序輸出,不含前導0,注意二進制數組是整型和字符型的操作不同哦,若char strB[];memset(strB,0,sizeof(strB));則全部賦值爲空,而不是字符型的‘0’;char strB[]={‘0’},只有第一個賦值爲字符型的‘0’,其他全部爲空哦。
整型數組代碼如下(轉換成的八進制數組也是整型哦):
int p=0;
for(i=0;i<k;i+=3) //三位二進制位對應一位八進制位,
strH[p++]=strB[i]+strB[i+1]*2+strB[i+2]*4;//正序的話,左側最高位權值最高,現在倒序,左側權值最低了哦
for(i=p-1;i>=0;i--)//倒序輸出對應的八進制位哦
{
if(strH[i]==0) //不含前導0,所以遇0不輸出哦
continue;
else
{
for(j=i;j>=0;j--)
printf("%d",strH[j]);
break;
}
}
字符型代碼如下:
int p=0;
for(i=0;i<k;i+=3) //三位二進制位對應一位八進制位,
{
if(k-i==2)
strB[i+2]='0';
else if(k-i==1)
strB[i+1]=strB[i+2]='0';
strH[p++]=(strB[i]-'0'+(strB[i+1]-'0')*2+(strB[i+2]-'0')*4)+'0';
}
//正序的話,左側最高位權值最高,現在倒序,左側權值最低了哦
for(i=p-1;i>=0;i--)//倒序輸出對應的八進制位哦
{
if(strH[i]=='0') //不含前導0,所以遇0不輸出哦
continue;
else
{
for(j=i;j>=0;j--)
printf("%c",strH[j]);
break;
}
}
倒序轉換,由於二進制的位數不一定是3的整數倍,所以可先將長度轉換成3的整數倍,即最後不足3的整數倍的位數補0(整型數組,字符型補字符型‘0’);
整型代碼如下:
k=k+3-k%3; //將二進制數組長度更新成3的倍數
k--; //二進制數組從0開始呢
while(strB[k]*4+strB[k-1]*2+strB[k-2]==0)
k-=3; //不含前導0,則將結果是0的部分去掉,即k直接向前跳呢
for(i=k;i>0;i-=3) //倒序輸出
{
int ans=strB[i]*4+strB[i-1]*2+strB[i-2];
printf("%d",ans);
}
整體代碼:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char strD[100000+11]; //輸入十六進制 ,用字符型
int strB[400000+11]; //十六進制對應二進制數,可用整型存儲
int strH[300000+11]; //二進制對應八進制數,用整型存儲
int main()
{
int n;
scanf("%d",&n);
while(n--)
{
memset(strB,0,sizeof(strB));
scanf("%s",strD);
int len1=strlen(strD);
if(strD[0]=='0'&&len1==1) //輸入只有一個0,那麼直接就輸出0咯
{
printf("0\n");
continue;
}
int j,k=0,i;
for(i=len1-1;i>=0;i--)//倒序,得到十六進制對應的二進制數組
{
j=4;
int flag;
if(strD[i]>='0'&&strD[i]<='9')
flag=strD[i]-'0';
else if(strD[i]>='A'&&strD[i]<='Z')
flag=strD[i]-'A'+10;
while(j--) //一位十六進制對應四位二進制,連除四次,保留餘數
{
strB[k++]=(flag%2);
flag>>=1;
}
}
int p=0;
for(i=0;i<k;i+=3) //三位二進制位對應一位八進制位,
strH[p++]=strB[i]+strB[i+1]*2+strB[i+2]*4;//正序的話,左側最高位權值最高,現在倒序,左側權值最低了哦
for(i=p-1;i>=0;i--)//倒序輸出對應的八進制位哦
{
if(strH[i]==0) //不含前導0,所以遇0不輸出哦
continue;
else
{
for(j=i;j>=0;j--)
printf("%d",strH[j]);
break;
}
}
/* k=k+3-k%3; //將二進制數組長度更新成3的倍數
k--; //二進制數組從0開始呢
while(strB[k]*4+strB[k-1]*2+strB[k-2]==0)
k-=3; //不含前導0,則將結果是0的部分去掉,即k直接向前跳呢
for(i=k;i>0;i-=3) //倒序輸出
{
int ans=strB[i]*4+strB[i-1]*2+strB[i-2];
printf("%d",ans);
}*/
printf("\n");
}
return 0;
}