基础练习 十六进制转八进制

问题描述
  给定n个十六进制正整数,输出它们对应的八进制数。

输入格式
  输入的第一行为一个正整数n (1<=n<=10)。
  接下来n行,每行一个由0~9、大写字母A~F组成的字符串,表示要转换的十六进制正整数,每个十六进制数长度不超过100000。

输出格式
  输出n行,每行为输入对应的八进制正整数。

  【注意
  输入的十六进制数不会有前导0,比如012A。
  输出的八进制数也不能有前导0。

样例输入
  2
  39
  123ABC

样例输出
  71
  4435274

  提示
  先将十六进制数转换成某进制数,再由某进制数转换成八进制。

代码

#include <stdio.h>
#include <string.h>
char h[100002],b[400008],e[400008]; //十六、二、八
int main()
{
int n;
scanf("%d",&n);   //输入待换的十六进制数总数
while(n--)  //对这些数逐一处理
{
scanf("%s",h);  
int i,len=0;  //len是未来转化成的二进制数长度
for(i=strlen(h)-1;i>=0;i--)   //对十六进制数从右往左进行处理(低位到高位)
{
int v,j;   //v是十六进制数每位的值(如该位为'A' 则v=10)
if(h[i]>='0'&&h[i]<='9')   //0~9(16)
v=h[i]-'0';  //将字符转化为其值
else  //A~F(16)
v=h[i]-'A'+10;
for(j=0;j<4;j++)  //用4位的二进制表示一位十六进制
{
b[len++]=v%2+'0';  //v%2为值,加上‘0’可转化为字符

v/=2;
}
}
b[len]='\0';  //最高位补0 无影响(终止符?没看出啥用)
int x=0,cnt=1,l=0;  //x为八进制某位的值,cnt为位权(如四位二进制即8-4-2-1),l为未来八进制数组下标
for(i=0;i<len;i++)  
{
if(cnt==4||i==len-1)  //每到4位或最低位情况时位权取1(3位一换)
{
x=cnt*(b[i]-'0')+x;  
cnt=1;
e[l++]=x+'0';
x=0;  //注意x清零 每3位整体计算一位数(八进制)
}
else
{
x=cnt*(b[i]-'0')+x;   
cnt*=2;
}
}
i=l-1;  
while(i>=0&&e[i]=='0')   //消除前导0
i--;
if(i<0)   //输入为0的情况
printf("0");
for(;i>=0;i--)   //倒序输出八进制数组
{
printf("%c",e[i]);
}
printf("\n");
}
return 0;
}

思考

一开始想16转10再转8 结果出不来otz现在想想可能是输入字符串的时候没清空?

没有耐心直接借鉴了百度otz非原创 将大佬的代码拆了一遍 注释如上(大佬太强了 其实有些细节莫得看懂 跪倒)

思路就是16转2转8 用了3个字符数组表示三种形态

需要注意的点有:

1.三个数组输入顺序 16(高位到低位) 2(低位到高位)8(高位到低位) 所以对应的for也不同

2.16转2是1换4 2换8是3换1 所以子循环里面的条件要注意

3.16转2其实中间有涉及到10 用整型v暂存了 所以可拆为16转10(值)10转2(字符)2转8则需考虑3换1的实现问题 在第四位及最低位时位权都为1

4.前导0需消除,这里直接忽略该位

我像个单细胞的小学生一样看了好久好久代码...晕倒 拖延症杀我

 

posted @ 2020-02-05 23:04  Shawuila  阅读(426)  评论(1编辑  收藏  举报