DotcppXF


私信TA

用户名:dotcpp0599925

访问量:4433

签 名:

层楼终究误少年

等  级
排  名 191
经  验 6470
参赛次数 0
文章发表 13
年  龄 0
在职情况 学生
学  校 华南理工大学
专  业 计算机科学与技术

  自我简介:

The sad truth is, not everyone will accomplish something great. Some of us may just have to find meaning in the little moments that make up life.


【解题思路】


        ① 首先题目输入要求每个十六进制数长度不超过100000,注意是“长度”不是“大小”,所以没办法直接用%x和%o来进行输入输出了;

        ② 这题需要进行大数的进制转换,正常可以通过先将十六进制转为二进制,再将二进制转为八进制输出,也可根据两个进制转换的规律直接转换。



【1】进制转换对照表


        1664273953857659.jpg


        1664274149258947.jpg


        上面的表大家都比较熟悉了,当然是加上了前导0的,1位十六进制的数需要4位二进制的数来表示,1位八进制的数需要3位二进制的数来表示。



【2】多位数进制转换对照表(以十六进制数“C6A4”为例)


        1664282969276.jpg


        1664283122942.jpg


        ① 先看黄色区域部分,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 人评分

看不懂代码?想转换其他语言的代码? 或者想问其他问题? 试试问问AI编程助手,随时响应你的问题:

编程语言转换

万能编程问答

代码解释器

  评论区