蓝桥杯:大数十六进制转八进制简易思路
1.思路分析:
总思路:先将十六进制转化成某进制,再由此进制转成八进制。
①数据类型的分析:
看题目不难看出十六进制位数很多,整型不易很好表达大数的算法。故我们使用字符串数组表达大数。
②转化进制的分析:
如果使用十进制作为中介进制的话,转化起来相对比较麻烦,需要先按权展开算出转化的十进制数值,再用除八取余法算出八进制数值,最后通过按位保存在字符串数组里。
如果使用二进制作为中介进制的话,转化起来就非常的简单。一位四进制转四位二进制,然后将三位二进制转化成一位八进制存储。
2.实现过程:
①变量声明及其作用:
int n; //n记录十六进制个数
int i,j; //i,j循环控制变量
char **data; //保存多个十六进制字符串数组
char oct[133334]; //八进制数
char bin[400000]; //二进制数
int count; //计算十六转二进制的个数
int temp; //作为临时变量,用于中间数值计算
②输入数据及保存
scanf("%d",&n); //十六进制个数
getchar(); //接收scanf垃圾消息'\n'
data=(char **)malloc(n*sizeof(char *));
for(i=0;i<n;i++)
{
data[i]=(char*)malloc(100000*sizeof(char));
}//动态分配存储
for(i=0;i<n;i++)
{
gets(data[i]);
} //输入十六进制数
③数据的处理
我们使用循环语句让每个十六进制都可进行处理(每次循环开头需要初始化数据)
for(i=0;i<n;i++)
{
//处理数据代码段
}
ⅰ数据的初始化
for(j=0;data[i][j]!='\0';j++);
count=j*4;//计算出十六进制转二进制位数
for(j=0;bin[j]!='\0';j++)
{
bin[j]='\0';
}//二进制数组清空;
for(j=0;oct[j]!='\0';j++)
{
oct[j]='\0';
}//八进制数组清空;
ps:算出二进制位数是为了更好的将二进制转八进制。因为转化的时候不是每次都是3的倍数正好可以转成八进制。所以我们需要在转化以后的二进制前面加入若干的个0以便后面转化更加简单;
添加0的代码如下:
if(count%3!=0)
{
for(j=0;(j+count)%3!=0;j++)
{
bin[j]='0';
}
temp=j; //记录第一个非0元素的位置信息
}//将二进制数组个数变成3的倍数
else
count=0;
ⅱ十六进制转二进制代码
for(j=0;data[i][j]!='\0';j++)
{
strcpy(&bin[4*j+temp],trans(data[i][j]));
}//十六转3倍个数的二进制
trans函数为:
char * trans(char a)
{
switch(a){
case '0': return "0000";
case '1': return "0001";
case '2': return "0010";
case '3': return "0011";
case '4': return "0100";
case '5': return "0101";
case '6': return "0110";
case '7': return "0111";
case '8': return "1000";
case '9': return "1001";
case 'A': return "1010";
case 'B': return "1011";
case 'C': return "1100";
case 'D': return "1101";
case 'E': return "1110";
case 'F': return "1111";
}
}
trans函数的作用就是将每位十六进制数返回四位二进制字符串常量。利用字符串的复制函数将字符串常量复制到bin字符串数组。
ⅲ由二进制转化成八进制代码
for(j=0;bin[j*3]!='\0';j++)
{
temp=(bin[j*3]-48)*4+(bin[j*3+1]-48)*2+(bin[j*3+2]-48);
oct[j]=temp+48;
} //'0'=48
我们巧妙的利用了数值和字符串数字的差进行计算,转化成八进制代码。
但这个时候可能存在一种情况,保存的八进制数值含有若干的0的情况,根据八进制概念,我们知道八进制前没有0;
故我们做如下操作
for(j=0;oct[j]=='0';j++);//找到第一个非0八进制位置;
puts(&oct[j]);
ⅳ扫尾工作
if(data!=0)
{
for(i=0;i<n;i++)
{
free(data[i]);
}
free(data);
data=0;
}
3.代码总结(与过程分析过程代码顺序一致)
#include <stdio.h>
#include <string.h>
#include <malloc.h>
char * trans(char a)
{
switch(a){
case '0': return "0000";
case '1': return "0001";
case '2': return "0010";
case '3': return "0011";
case '4': return "0100";
case '5': return "0101";
case '6': return "0110";
case '7': return "0111";
case '8': return "1000";
case '9': return "1001";
case 'A': return "1010";
case 'B': return "1011";
case 'C': return "1100";
case 'D': return "1101";
case 'E': return "1110";
case 'F': return "1111";
}
}
int main()
{
int n; //n记录十六进制个数
int i,j; //i,j循环控制变量
char **data; //保存多个十六进制字符串数组
char oct[133334]; //八进制数
char bin[400000]; //二进制数
int count; //计算十六转二进制的个数
int temp; //作为临时变量,用于中间数值计算
scanf("%d",&n);
getchar();
data=(char **)malloc(n*sizeof(char *));
for(i=0;i<n;i++)
{
data[i]=(char*)malloc(100000*sizeof(char));
}
for(i=0;i<n;i++)
{
gets(data[i]);
}
for(i=0;i<n;i++)
{
for(j=0;data[i][j]!='\0';j++);
count=j*4;
for(j=0;bin[j]!='\0';j++)
{
bin[j]='\0';
}//清空;
for(j=0;oct[j]!='\0';j++)
{
oct[j]='\0';
}//清空;
if(count%3!=0)
{
for(j=0;(j+count)%3!=0;j++)
{
bin[j]='0';
}
count=j;
}//将二进制数组个数变成3的倍数
else
count=0;
for(j=0;data[i][j]!='\0';j++)
{
strcpy(&bin[4*j+temp],trans(data[i][j]));
}//十六转3倍个数的二进制
for(j=0;bin[j*3]!='\0';j++)
{
temp=(bin[j*3]-48)*4+(bin[j*3+1]-48)*2+(bin[j*3+2]-48);
oct[j]=temp+48;
} //'0'=48
for(j=0;oct[j]=='0';j++)
{
;
}
puts(&oct[j]);
}
if(data!=0)
{
for(i=0;i<n;i++)
{
free(data[i]);
}
free(data);
data=0;
}
return 0;
}