十六进制转八进制

/*
问题描述:
给定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>
int main(){
	char hex[100000],bin[400002],oct[400002];//声明数组时为了防止内存溢出,将oct[400002]申明为字符数组而不是整型数组(一个字符占一个字节,而一个整形占四个字节),在后面加“+'0'”即可体现出字符的形式 
	int l,n,i,j,k,v,len,counter,len2,len3;
	scanf("%d",&n);
	for(l=0;l<n;l++){//l用来计数大的循环,防止后面用到了i对外循环造成影响
		memset(bin,0,sizeof(bin));//不能用strcpy(bin,"")来,这个strcpy只是将这个长度为1的""的给bin这个数组的第一位,后面的不会变,覆盖不了 
		memset(oct,0,sizeof(oct));//不能用strcpy(oct,"")来,这个strcpy只是将这个长度为1的""的给oct这个数组的第一位,后面的不会变,覆盖不了
		scanf("%s",hex);
		len=strlen(hex);
/*十六进制转换为八进制需要分组,不够的补位*/		
		if(len*4%3==1){
			bin[0]=bin[1]='0';
			counter=2;
			for(j=0;j<len;j++){
				if(hex[j]>='0'&&hex[j]<='9')
					v=hex[j]-'0';
				else/*这个if-else语句是在将十六进制数换为相应的十进制数(十进制数才能做除法)用来通过算法换为二进制数
					  而且这里的v很巧妙,只用了一个整形变量,而没有用一个整形数组来装相应的十六进制转换为的十进制数,要换一个时即可,不用了就替代,不必再用一个整型数组来装,浪费内存*/ 
					v=hex[j]-'A'+10;
/*一个十六进制数转化为四个二进制数,在这里用一个小循环确保始终能够有四位二进制数产生(学习这种思路)*/ 
				for(k=3;k>=0;k--){
					bin[counter+k]=v%2+'0';//加上'0'将整型体现出字符的形式 
					v=v/2;//注意:这里出来的4位2进制,到最后的时候,不是数字的自动补零
				}
/*一个十六进制数转化为四个二进制数,在这里用一个小循环确保始终能够有四位二进制数产生*/ 
				counter=counter+4;
			}
		}
		else if(len*4%3==2){
			bin[0]='0';
			counter=1;
			for(j=0;j<len;j++){
				if(hex[j]>='0'&&hex[j]<='9')
					v=hex[j]-'0';
				else
					v=hex[j]-'A'+10;
				for(k=3;k>=0;k--){
					bin[counter+k]=v%2+'0';//加上'0'将整型体现出字符的形式 
					v=v/2;
				}
				counter=counter+4;
			}
		}
		else{
			counter=0;
			for(j=0;j<len;j++){
				if(hex[j]>='0'&&hex[j]<='9')
					v=hex[j]-'0';
				else
					v=hex[j]-'A'+10;
				for(k=3;k>=0;k--){
					bin[counter+k]=v%2+'0';//加上'0'将整型体现出字符的形式 
					v=v/2;
				}
				counter=counter+4;
			}
		}
/*十六进制转换为八进制需要分组,不够的补位*/
		len2=strlen(bin);//len2代表二进制后的长度
		for(i=0,k=0;i<len2;i=i+3,k++)//i=i+3不是i+3
			oct[k]=(bin[i]-'0')*4+(bin[i+1]-'0')*2+(bin[i+2]-'0')*1+'0';//加上'0'将整型体现出字符的形式,仅限于该字符为数字时 
		len3=len2/3;//len3代表八进制后的长度
		if(oct[0]=='0'){
			for(i=1;i<len3;i++)
				printf("%c",oct[i]);
			printf("\n");//这样换行,在for循环完了之后加一句这个就换行了,不需再用if(i==len2)什么的来判断 
		}
		else{
			for(i=0;i<len3;i++)
				printf("%c",oct[i]);
			printf("\n");//这样换行,在for循环完了之后加一句这个就换行了,不需再用if(i==len2)什么的来判断 
		}
	}
	return 0;
}

/*--------------------------------------------------------------------------------------------------------------------------------------------------------
另外:这种将十六进制转换为二进制的方法也不错,巧用strcat函数
		if(len*4%3==1){
			str2[0]=str2[1]='0';
			for(k=0;k<len;k++){
				switch(str[k]){
					case '0':strcat(str2,"0000");break;
					case '1':strcat(str2,"0001");break;
					case '2':strcat(str2,"0010");break;
					case '3':strcat(str2,"0011");break;
					case '4':strcat(str2,"0100");break;
					case '5':strcat(str2,"0101");break;
					case '6':strcat(str2,"0110");break;
					case '7':strcat(str2,"0111");break;
					case '8':strcat(str2,"1000");break;
					case '9':strcat(str2,"1001");break;
					case 'A':strcat(str2,"1010");break;
					case 'B':strcat(str2,"1011");break;
					case 'C':strcat(str2,"1100");break;
					case 'D':strcat(str2,"1101");break;
					case 'E':strcat(str2,"1110");break;
					case 'F':strcat(str2,"1111");break;
				}
			}
			len2=strlen(str2)/3;//这样求新的转化为八进制后的长度,不用自己去想算法了
		}
		else 
		if(len*4%3==2){
			str2[0]='0';
			for(k=0;k<len;k++){
				switch(str[k]){
					case '0':strcat(str2,"0000");break;
					case '1':strcat(str2,"0001");break;
					case '2':strcat(str2,"0010");break;
					case '3':strcat(str2,"0011");break;
					case '4':strcat(str2,"0100");break;
					case '5':strcat(str2,"0101");break;
					case '6':strcat(str2,"0110");break;
					case '7':strcat(str2,"0111");break;
					case '8':strcat(str2,"1000");break;
					case '9':strcat(str2,"1001");break;
					case 'A':strcat(str2,"1010");break;
					case 'B':strcat(str2,"1011");break;
					case 'C':strcat(str2,"1100");break;
					case 'D':strcat(str2,"1101");break;
					case 'E':strcat(str2,"1110");break;
					case 'F':strcat(str2,"1111");break;
				}
			}
			len2=strlen(str2)/3;//这样求新的转化为八进制后的长度,不用自己去想算法了
		}
		else{
			for(k=0;k<len;k++){
				switch(str[k]){
					case '0':strcat(str2,"0000");break;
					case '1':strcat(str2,"0001");break;
					case '2':strcat(str2,"0010");break;
					case '3':strcat(str2,"0011");break;
					case '4':strcat(str2,"0100");break;
					case '5':strcat(str2,"0101");break;
					case '6':strcat(str2,"0110");break;
					case '7':strcat(str2,"0111");break;
					case '8':strcat(str2,"1000");break;
					case '9':strcat(str2,"1001");break;
					case 'A':strcat(str2,"1010");break;
					case 'B':strcat(str2,"1011");break;
					case 'C':strcat(str2,"1100");break;
					case 'D':strcat(str2,"1101");break;
					case 'E':strcat(str2,"1110");break;
					case 'F':strcat(str2,"1111");break;
				}
			}
			len2=strlen(str2)/3;//这样求新的转化为八进制后的长度,不用自己去想算法了
		}*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值