蓝桥杯:(c语言)大数十六进制转八进制简易思路

蓝桥杯:大数十六进制转八进制简易思路

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;
}

第一次写这么长的文章,希望有人可以多看看,可以收获很多的。如果感觉对你有帮助可以收藏一下,并转发给更多人,让大家一起共同进步。

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值