基础练习 十六进制转八进制
问题描述
给定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需消除,这里直接忽略该位
我像个单细胞的小学生一样看了好久好久代码...晕倒 拖延症杀我