蓝桥杯基础 进制转换问题

问题描述

  给定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

posted @ 2018-01-17 18:25  Curo  阅读(421)  评论(0编辑  收藏  举报