问题描述
给定n个十六进制正整数,输出它们对应的八进制数。
输入格式
输入的第一行为一个正整数n (1<=n<=10)。
接下来n行,每行一个由0~9、大写字母A~F组成的字符串,表示要转换的十六进制正整数,每个十六进制数长度不超过100000。
输出格式
输出n行,每行为输入对应的八进制正整数。
【注意】
输入的十六进制数不会有前导0,比如012A。
输出的八进制数也不能有前导0。
样例输入
2
39
123ABC
样例输出
71
4435274
【提示】
先将十六进制数转换成某进制数,再由某进制数转换成八进制。
---初看这道题,想的就是把十六进制数转成十进制数,再转回成八进制就好,事实证明我错了....它要求的数据规模是不大于100000,显然转成十进制是不妥当的。
先把用十进制转的错误思想代码贴在这里。
1 #include<stdio.h> 2 #include<iostream> 3 #include<math.h> 4 #include<string> 5 using namespace std; 6 char str[100000]; 7 int eight[100000]; 8 int main() 9 { 10 int i,j; 11 int n; 12 scanf("%d",&n); 13 int num; 14 while(n--) 15 { 16 num=0; 17 scanf("%s",&str); 18 int len=strlen(str); 19 //十六进制转十进制 20 for(i=len-1;i>=0;i--) 21 { 22 if(str[i]>=‘0‘&&str[i]<=‘9‘) 23 num+=pow(16,len-1-i)*(str[i]-‘0‘); 24 else if(str[i]>=‘A‘&&str[i]<=‘F‘) 25 num+=pow(16,len-1-i)*(str[i]-‘A‘+10); 26 } 27 28 //printf("%d\n",num); 29 //十进制转八进制 30 i=0; 31 while((num/8)!=0) 32 { 33 eight[i]=num%8; 34 num=num/8; 35 i++; 36 } 37 eight[i]=num;//否则最后一次存入数据会丢失(首位丢失) 38 for(int j=i;j>=0;j--) 39 { 40 printf("%d",eight[j]); 41 } 42 } 43 44 return 0; 45 }
总结网上各路大神的代码,大概有一下思路:
1.直接映射的,所有的过程都是以字符串形式的。每个16进制数(字符串形式)转成4位二进制数(字符串形式)。第二第三行在内存上是一样的,只是在读取的时候第二行是从右往左每4位是一起是一个16进制数;而第三行在读取得时候是从右往左每三位是一个8进制数。第二行(在内存上也是第三行)也是每一位是一个字符存储起来的字符串。
1 #include <iostream> 2 #include <string> 3 using namespace std; 4 int arr[10000001]; 5 6 int main() 7 { 8 int n,len_str,i,j; 9 string str,str2; 10 cin>>n; 11 while(n--) 12 { 13 cin>>str; 14 len_str=str.length(); 15 str2=""; 16 17 // 十六进制转换为二进制 18 for(i=0;i<len_str;++i) 19 { 20 switch(str[i]) 21 { 22 case ‘0‘:str2+="0000";break; 23 case ‘1‘:str2+="0001";break; 24 case ‘2‘:str2+="0010";break; 25 case ‘3‘:str2+="0011";break; 26 case ‘4‘:str2+="0100";break; 27 case ‘5‘:str2+="0101";break; 28 case ‘6‘:str2+="0110";break; 29 case ‘7‘:str2+="0111";break; 30 case ‘8‘:str2+="1000";break; 31 case ‘9‘:str2+="1001";break; 32 case ‘A‘:str2+="1010";break; 33 case ‘B‘:str2+="1011";break; 34 case ‘C‘:str2+="1100";break; 35 case ‘D‘:str2+="1101";break; 36 case ‘E‘:str2+="1110";break; 37 case ‘F‘:str2+="1111";break; 38 default:break; 39 } 40 } 41 42 // 修正位数 43 if(len_str%3==1) str2="00"+str2; 44 45 else if(len_str%3==2) str2="0"+str2; 46 47 48 len_str=str2.length(); 49 // 二进制转换八进制 50 j=0; 51 for(i=0;i<=len_str-2;i+=3) 52 { 53 arr[j]=(str2[i]-‘0‘)*4+(str2[i+1]-‘0‘)*2+(str2[i+2]-‘0‘); 54 ++j; 55 } 56 57 for(i=0;i<j;++i) 58 { 59 if(i==0 && arr[i]==0) continue; 60 cout<<arr[i]; 61 } 62 cout<<endl; 63 64 } 65 return 0; 66 }
但是这样的实现确实麻烦,关键是二进制字符串占用内存很大,switch映射还要考虑补位,因为假设原来的十六进制数时14位,那么前12位是48位二进制数,也就是16个8进制数,但是剩下的两个十六进制数是8位二进制数,要变成8进制数要补一个二进制位(在字符串前面加个‘0‘),这种就是补位。
有没有更好的实现方法呢?见博客http://blog.csdn.net/qsyzb/article/details/18891219