【解题思路】
① 首先题目输入要求每个十六进制数长度不超过100000,注意是“长度”不是“大小”,所以没办法直接用%x和%o来进行输入输出了;
② 这题需要进行大数的进制转换,正常可以通过先将十六进制转为二进制,再将二进制转为八进制输出,也可根据两个进制转换的规律直接转换。
【1】进制转换对照表
上面的表大家都比较熟悉了,当然是加上了前导0的,1位十六进制的数需要4位二进制的数来表示,1位八进制的数需要3位二进制的数来表示。
【2】多位数进制转换对照表(以十六进制数“C6A4”为例)
① 先看黄色区域部分,3位十六进制的数需要12位二进制的数表示(包括前导0的位数),4位八进制的数也需要12位二进制的数表示(包括前导0的位数),也就是说3位十六进制的数是可以正好转换为4位八进制的数的;
② 再看绿色区域部分,只剩1位十六进制的数需要4位二进制的数表示,需要加上两位前导0,凑成6位二进制的数再转换为2位八进制的数。
【3】以3位数为一个循环,将十六进制的数转换为八进制的数
通过上述对比,解决大数据的进制转换思路也就出来了:
① 用字符串输入十六进制的数,数组按题目要求开100000以上即可;
② 将每个字符转换为可以运算的整数;
③ 利用位运算将每个数存放进另一个用来输出八进制数的数组,数组开133333以上即可;
④ 判断并处理边界,倒序输出这个新的数组。
【4】位运算的实现方式
假设整型变量m表示每一位十六进制的数,b[j]表示储存八进制数的数组,还是以上述“C6A4”为例:
① 当m=4(4)时:需要提取【0100】中的后3位【100】储存进八进制的数组,同时留下了第1位【0】供下一位处理;
s=m; // s用来存放留下的位 b[j++]=s&7; // 7的2进制表示为0111,与其他数“按位与”处理后得到的就是后三位的数 s=s>>3; // 也可以用s/=8代替,表示“右移”3位,将剩下的1位留在s里
② 当m=10(A)时:需要提取【1010】中的后2位【10】加上上一位留下的【0】组成【100】储存进八进制的数组,同时留下了前2位【10】供下一位处理;
s+=m<<1; // m<<1等价于m*2,将m左移1位后与上面留下的1位相加 b[j++]=s&7; s=s>>3; // “右移”3位,将剩下的2位留在s里
③ 当m=6(6)时:需要提取【0110】中的后1位【0】加上上一位留下的【10】组成【010】储存进八进制的数组,同时留下的前3位【011】也再次储存进八进制的数组。
s+=m<<2; // m<<2等价于m*4,将m左移2位后与上面留下的2位相加 b[j++]=s&7; s=s>>3; // “右移”3位,将剩下的3位留在s里 b[j++]=s&7; s=s>>3; // 处理后s为0,不再留有任何位的数
④ 当m=12(C)时:这时候发现,上一位没有留下多余的位数需要这一位处理了,也就是又开始了一轮新的3位循环,处理方式和m=4时一样;
⑤ 已经将所有十六进制数处理完,但还有前一位留下的【1】没有处理,单独处理即可。
【注意事项】
① 3位循环处理时,判断当前位属于哪一位一定不要出错!!!
② 处理结果可能会存在前导0的情况,需要加以判断!!!
【参考代码】
#include<stdio.h> #include<string.h> int main(void) { char a[100000]; int b[150000],n,m,i,j,s; scanf("%d",&n); while(n--) // 输入n个实例 { scanf("%s",a); for(i=strlen(a)-1,j=0;i>=0;i--) { if(a[i]>='0'&&a[i]<='9') // 将每位字符转换为可处理的整数 m=a[i]-'0'; else m=a[i]-'A'+10; switch((strlen(a)-i)%3) // 判断是3位循环中的哪一位 { case 1: s=m;b[j++]=s&7;s/=8;break; case 2: s+=m*2;b[j++]=s&7;s/=8;;break; default: s+=m*4;b[j++]=s&7;s/=8;b[j++]=s&7;s/=8; } } if(s>0) // 判断是否存在多余的位没处理,直接输出 printf("%o",s); for(i=j-1;i>=0;i--) // 输出剩余的每一位八进制数 if(!(i==j-1&&b[i]==0&&s==0)) // 判断排除先导0 printf("%d",b[i]); printf("\n"); } return 0; }
0.0分
3 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复