问题描述
给定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>
#define N 100100
int HexToBin(char *hex, char *bin, int n)
{
int i, j, len = 4*n, num, count = 0;
if(len%3 == 1) //将bin的长度len凑成3的整数倍,便于转换为八进制
len += 2;
else if(len%3 == 2)
len++;
//下面这一行代码的功能为:
//如果hex转bin时没有一直赋值到bin[len-1],则由于main()中bin被初始化为全为'\0',
//bin的实际长度还是没有到达len就被'\0'截断了;
//如果对len-4~len-1手动赋值,则长度一定到了len。
//或者也可以选择在这里将bin从bin[0]到bin[len-1]初始化为全'0',效果等同
bin[len-1] = bin[len-2] = bin[len-3] = bin[len-4] = '0';
for(i=n-1; i>=0; i--)
{
switch(hex[i])
{
case 'A' : num = 10; break;
case 'B' : num = 11; break;
case 'C' : num = 12; break;
case 'D' : num = 13; break;
case 'E' : num = 14; break;
case 'F' : num = 15; break;
default : num = hex[i] - '0';
}
for(j=0; j<=3; j++)
{
bin[count*4 + j] = num%2 + '0';
num /= 2;
}
count++;
}
return len;
}
int BinToOct(char *bin, char *oct, int len_bin)
{
int i, j = 0, value = 0;
for(i=0; i<len_bin; i += 3)
{
value = 1*(bin[i + 0] - '0') + 2*(bin[i + 1] - '0') + 4*(bin[i + 2] - '0');
oct[j++] = value + '0';
}
return j;
}
void Print(char *oct, int len_oct)//此时的oct如果倒着输出,就是正确的八进制,当然别忘了前导零
{
int i = len_oct - 1;
while(oct[i] == '0') //相当于去除“前导”零
i--;
for(; i>=0; i--) //倒序输出
putchar(oct[i]);
putchar('\n');
}
int main()
{
int n, len_bin, len_oct;
char hex[N] = {0}, bin[4*N] = {0}, oct[3*N] = {0};
scanf("%d", &n);
getchar(); //scanf()下面一次读数的是gets(),所以中间要加getchar()去掉'\n'
while(n--)
{
memset(hex, 0, N);
memset(bin, 0, 4*N);
memset(oct, 0, 3*N);
gets(hex); //gets()后不用加getchar(),因为'\n'被ets()读为'\0'到hex中
//getchar();
len_bin = HexToBin(hex, bin, strlen(hex));
len_oct = BinToOct(bin, oct, len_bin);
Print(oct, len_oct);
}
return 0;
}