蓝桥杯 基础练习 十六进制转八进制(5)超长字符串处理

 基础练习 十六进制转八进制  
时间限制:1.0s   内存限制:512.0MB
问题描述
  给定n个十六进制正整数,输出它们对应的八进制数。

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

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

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

样例输入
  2
  39
  123ABC

样例输出
  71
  4435274

   提示
  先将十六进制数转换成某进制数,再由某进制数转换成八进制。
总结,本题牵涉到几个细节:

  1. 采用gets输入时,需要处理%d在输入流中留下的回车;
  2. 合理定义数组大小,其中十六进制位数与二进制是4倍关系,与八进制是4/3关系;
  3. 使用strcat拼接字符串时注意,为了加快速度,需采用下文中方式,否则会超时(避免每次都从字符串首部查找'\0');
  4. 对于所得二进制可能不为3的整数倍时,01,101,110,101.....,这里采用取余法将01单独处理,后面整体处理;
  5. 由于采用了while(scanf('')!=EOF)输入形式,注意每次对尾部进行截断,避免对下次计算造成影响;
  6. 以下程序采用纯C语言编写。

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

char Hex[10][100001]; // 十六进制
char Oct[10][150000]; // 八进制 将列数扩大4/3倍以上
char Bin[10][400004]; // 二进制 将列数扩大为4倍以上

//十六进制转二进制
void Hex2Bin(int row)
{
	int hexcol=0, bincol=0;

	Bin[row][0] = '\0';   //strcat 识别'\0'
	while (Hex[row][hexcol] != '\0')
	{
		switch (Hex[row][hexcol])
		{//&Bin[row][bincol]   比直接使用Bin[row]速度快,避免从头查找'\0'
			case '0': strcat(&Bin[row][bincol],"0000"); break;
			case '1': strcat(&Bin[row][bincol],"0001"); break;
			case '2': strcat(&Bin[row][bincol],"0010"); break;
			case '3': strcat(&Bin[row][bincol],"0011"); break;
			case '4': strcat(&Bin[row][bincol],"0100"); break;
			case '5': strcat(&Bin[row][bincol],"0101"); break;
			case '6': strcat(&Bin[row][bincol],"0110"); break;
			case '7': strcat(&Bin[row][bincol],"0111"); break;
			case '8': strcat(&Bin[row][bincol],"1000"); break;
			case '9': strcat(&Bin[row][bincol],"1001"); break;
			case 'A': strcat(&Bin[row][bincol],"1010"); break;
			case 'B': strcat(&Bin[row][bincol],"1011"); break;
			case 'C': strcat(&Bin[row][bincol],"1100"); break;
			case 'D': strcat(&Bin[row][bincol],"1101"); break;
			case 'E': strcat(&Bin[row][bincol],"1110"); break;
			case 'F': strcat(&Bin[row][bincol],"1111"); break;
		}
		++hexcol;	
		bincol += 4;
	}
//	puts(Bin[row]);
}

//二进制转八进制
void Bin2Oct(int row)
{
	int bincol,octcol=0,mod,num,curcol=0,flag=0;
	//curcol 表示当前扫描到二进制位置
	//flag用来标记首部是否已经出现了非0元素
	
	bincol = strlen(Bin[row]);
	mod = bincol % 3;  // 解决01, 101,110,011...问题,
	                   //划分为2部分分别计算
	                   //01------101,110,011
	//单独计算01
	num = 0;
	while (--mod >= 0)
	{
		if (Bin[row][curcol++] == '1')
			num += (int)pow(2,mod);
	}
	//跳过首部0
	if (num != 0)
	{
		Oct[row][octcol++] = '0'+num; //转数字为字符
		flag = 1;  //标记第一个不为0位置
	}
	//计算101,110,011...
	while (Bin[row][curcol] != '\0')
	{
		mod = 3; num = 0;  //每3位一计算,2^2=4,  2^1=2,  2^0=1
		while (--mod >= 0)
		{
			if (Bin[row][curcol++] == '1')
				num += (int)pow(2,mod);
		}
		//跳过首部0
		if (num != 0 || flag == 1)
		{
			Oct[row][octcol++] = '0'+num; //转数字为字符
			flag = 1;
		}
	}
	//将尾部截断
	Oct[row][octcol] = '\0';
}
//十六进制转八进制
void Hex2Oct(int n)
{
	int row;

	for (row = 0; row < n; ++row)
	{
		Hex2Bin(row);  // 16->2
		Bin2Oct(row);  // 2->8
	}

}


int main(void)
{
	int row,n;
	
	while (scanf("%d",&n) != EOF)  
	{
		getchar();  //消除输入流——回车误差
		
		for (row = 0; row < n; ++row)
		{
			gets(Hex[row]);
		}
		//十六进制转八进制
		Hex2Oct(n);
		//打印
		for (row = 0; row < n; ++row)
		{
			puts(Oct[row]);
		}
	}

	return 0;
}


Copyright © 2017 KINGDOM. All rights reserved.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值