蓝桥杯 c语言 十六进制转八进制

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

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

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

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

样例输入
  2
  39
  123ABC

样例输出
  71
  4435274

【提示】
  先将十六进制数转换成某进制数,再由某进制数转换成八进制。
之前看了大佬的代码,都觉得直接定义出400000长的字符数组不现实,但是通过相关测试后,字符串数组的最大长度应该为2000000。
解题思路为先把16进制通过1拆4转为2进制,在3合1转为8进制。

#include <stdio.h>
#include <malloc.h>
#include <string.h>

struct Shiliu{
	char s[1000001] ;
};
typedef struct Shiliu shiliu ;

struct Ba{
	char s[1000001] ;
};
typedef struct Ba ba ;

struct Er{
	char s[4000001] ;
};
typedef struct Er er ;

int main()
{
	int n ;
	scanf("%d",&n) ;
	shiliu* a = (shiliu*)malloc(n*sizeof(shiliu)) ;
	ba* c = (ba*)malloc(sizeof(ba)) ;
	er* b = (er*)malloc(sizeof(er)) ;
	for(int i=0;i<n;++i)
		scanf("%s",a[i].s) ;
		
	int number = 0 ;
	for(int i=0;i<n;++i)
	{//16转2 1拆4 
		number = 0 ;
		for(int j=0;a[i].s[j]!='\0';++j)
		{
			switch(a[i].s[j])
			{
				case '0':
					b->s[number++]='0';b->s[number++]='0';b->s[number++]='0';b->s[number++]='0';
					break ;
				case '1':
					b->s[number++]='0';b->s[number++]='0';b->s[number++]='0';b->s[number++]='1';
					break ;
				case '2':
					b->s[number++]='0';b->s[number++]='0';b->s[number++]='1';b->s[number++]='0';
					break ;
				case '3':
					b->s[number++]='0';b->s[number++]='0';b->s[number++]='1';b->s[number++]='1';
					break ;
				case '4':
					b->s[number++]='0';b->s[number++]='1';b->s[number++]='0';b->s[number++]='0';
					break ;
				case '5':
					b->s[number++]='0';b->s[number++]='1';b->s[number++]='0';b->s[number++]='1';
					break ;
				case '6':
					b->s[number++]='0';b->s[number++]='1';b->s[number++]='1';b->s[number++]='0';
					break ;
				case '7':
					b->s[number++]='0';b->s[number++]='1';b->s[number++]='1';b->s[number++]='1';
					break ;
				case '8':
					b->s[number++]='1';b->s[number++]='0';b->s[number++]='0';b->s[number++]='0';
					break ;
				case '9':
					b->s[number++]='1';b->s[number++]='0';b->s[number++]='0';b->s[number++]='1';
					break ;
				case 'A':
					b->s[number++]='1';b->s[number++]='0';b->s[number++]='1';b->s[number++]='0';
					break ;
				case 'B':
					b->s[number++]='1';b->s[number++]='0';b->s[number++]='1';b->s[number++]='1';
					break ;
				case 'C':
					b->s[number++]='1';b->s[number++]='1';b->s[number++]='0';b->s[number++]='0';
					break ;
				case 'D':
					b->s[number++]='1';b->s[number++]='1';b->s[number++]='0';b->s[number++]='1';
					break ;
				case 'E':
					b->s[number++]='1';b->s[number++]='1';b->s[number++]='1';b->s[number++]='0';
					break ;
				case 'F':
					b->s[number++]='1';b->s[number++]='1';b->s[number++]='1';b->s[number++]='1';
					break ;	
			}
			b->s[number]='\0' ;
		}
	//	printf("2进制%s\n",b->s) ;
		//2转8 
		number = 0 ;
		int sum = strlen(b->s) ;
//		for(int j=0;b[i].s[j]!='\0';++j)
//			++sum ;
		int j ;
		if(sum%3==0)
			j = 0 ;
		else if(sum%3==1)
			j = -2 ;
		else 
			j = -1 ;
		while(j<sum) //b->s[j]!='\0'
		{
			char temp[4] ;
			if(j==-2)
			{
				temp[0]='0';temp[1]='0'; j=0; temp[2]=b->s[j++] ; temp[3]='\0' ;
			}
			else if(j==-1)
			{
				temp[0]='0'; j=0; temp[1]=b->s[j++]; temp[2]=b->s[j++] ; temp[3]='\0' ;
			}
			else
			{
				temp[0]=b->s[j++];temp[1]=b->s[j++];temp[2]=b->s[j++];temp[3]='\0';
			}
			if(strcmp(temp,"000")==0)
				c->s[number++]='0';
			else if(strcmp(temp,"001")==0)
				c->s[number++]='1';
			else if(strcmp(temp,"010")==0)
				c->s[number++]='2';
			else if(strcmp(temp,"011")==0)
				c->s[number++]='3';
			else if(strcmp(temp,"100")==0)
				c->s[number++]='4';
			else if(strcmp(temp,"101")==0)
				c->s[number++]='5';
			else if(strcmp(temp,"110")==0)
				c->s[number++]='6';
			else if(strcmp(temp,"111")==0)
				c->s[number++]='7';
			c->s[number]='\0' ;
		//	printf("8进制%s\n",c->s) ;
		}
		int sign = 0 ;
		for(int k=0;;++k)
		{
			if(c->s[k]!='0')
			{
				sign = k ; break ;
			}
		}
		for(int k=sign;c->s[k]!='\0';++k)
			printf("%c",c->s[k]) ;
		printf("\n") ;
		b->s[0]='\0' ; c->s[0]='\0' ;
	}
	
	free(c) ; free(b) ;

	return 0 ;
}

欢迎讨论交流。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值