蓝桥杯练习系统_基础练习_十六进制转八进制

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/MM_GS/article/details/69486933

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

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

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

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

样例输入
  2
  39
  123ABC

样例输出
  71
  4435274

  提示
  先将十六进制数转换成某进制数,再由某进制数转换成八进制。

思路:
  先将十六进制数转换为二进制数,再以3位二进制数为一个整体转化为一个八进制数。

最初代码:
#include <iostream>
#include <string>
using namespace std;

int main()
{
	int n;
	cin>>n;
	string o[n],h[n];
	for (int i=0;i<n;i++)
	{
		cin>>h[i];
		
	}
	for (int j=0;j<n;j++)
	{
		int lens=h[j].length();
		string str=h[j];
		
		string b[lens],b1[lens];
		char a[lens];
		int ha=lens/3;
		int hb=lens%3;
		for (int t=0;t<lens;t++)
		{
			a[t]=str[t];
		}
		
		for (int k=0;k<lens;k++)
		{
			
			switch (a[k])
			{
				case '0': b[k]="0000";break;
				case '1': b[k]="0001";break;
				case '2': b[k]="0010";break;
				case '3': b[k]="0011";break;
				case '4': b[k]="0100";break;
				case '5': b[k]="0101";break;
				case '6': b[k]="0110";break;
				case '7': b[k]="0111";break;
				case '8': b[k]="1000";break;
				case '9': b[k]="1001";break;
				case 'A': b[k]="1010";break;
				case 'B': b[k]="1011";break;
				case 'C': b[k]="1100";break;
				case 'D': b[k]="1101";break;
				case 'E': b[k]="1110";break;
				case 'F': b[k]="1111";break;
			}
						
		}
		string str1;
		
		for (int n=0;n<lens;n++)
		{
			str1+=b[n];
		}
		
		int l=str1.length();
		int m=0;
		int hh=l/3+l%3;
		string s[hh];
		int t;
		for (t=l-1;t>1;t=t-3)
		{
			
			s[m]+=str1[t-2];
			s[m]+=str1[t-1];
			s[m]+=str1[t];
			m++;
		}
		if (t==1 || t==0)
		{
		
			m=m+1;
			int t1=2-t;
			
			if (t1=0)
			{
				s[m]="00";
				s[m]+=str1[t];
			}
			if (t1=1)
			{
				s[m]="0";
				s[m]+=str1[t-1];
				s[m]+=str1[t];
				
			}
		}
		char a1[m+1];
		for (int kk=m;kk>-1;kk--)
		{
			if (s[kk]=="000")
			{
				if (kk=m)
					;
				else
					a1[kk]='0';
			}
			if (s[kk]=="001")
				a1[kk]='1';
			if (s[kk]=="010")
				a1[kk]='2';
			if (s[kk]=="011")
				a1[kk]='3';
			if (s[kk]=="100")
				a1[kk]='4';
			if (s[kk]=="101")
				a1[kk]='5';
			if (s[kk]=="110")
				a1[kk]='6';
			if (s[kk]=="111")
				a1[kk]='7';
				
		} 
		string s2;
		for (int ll=0;ll<m+1;ll++)
		{
			s2[ll]=a1[m-ll];
			cout<<s2[ll];
		}
		cout<<s2<<endl;
	}
	
	return 0;
}

但是这个代码运行超时。
错误:二进制转八进制那里是将二进制全部转化完成存入字符串s2中,导致转化时的运行时间过长且占用空间太大。且代码太过繁杂。

成功代码:
#include <iostream>
#include <string>
using namespace std;

int main()
{
	int n;
	cin>>n;
	string h;
	for (int i=0;i<n;i++)
	{
		cin>>h;
		string s;
		int lens=h.length();
		for (int k=0;k<lens;k++)//十六进制转二进制 
		{
			switch (h[k])
			{
				case '0': s+="0000";break;
				case '1': s+="0001";break;
				case '2': s+="0010";break;
				case '3': s+="0011";break;
				case '4': s+="0100";break;
				case '5': s+="0101";break;
				case '6': s+="0110";break;
				case '7': s+="0111";break;
				case '8': s+="1000";break;
				case '9': s+="1001";break;
				case 'A': s+="1010";break;
				case 'B': s+="1011";break;
				case 'C': s+="1100";break;
				case 'D': s+="1101";break;
				case 'E': s+="1110";break;
				case 'F': s+="1111";break;
			}
		}
		
		int lens2=s.length();
		if (lens2%3==1) //lens2判断是否为3的倍数,不是则s前面补0 
		{
			s="00"+s;
		}
		else if(lens2%3==2)
		{
			s="0"+s;
		}
		int flag=0;//判断八进制数的首位是否为零 
		
		for (int j=0;j<lens2;j+=3)//三位二进制转为一位八进制 
		{
			int num=4*(s[j]-'0')+2*(s[j+1]-'0')+(s[j+2]-'0');
			if (num)
			{
				flag=1;
			}
			if (flag)
			{
				cout<<num;
			}
		}
		cout<<endl;
		
	}
	
	return 0;
}

改正后的代码,修改了许多不必要的繁杂,将十六转二的字符串链接直接在switch函数中完成,用二进制的字符串长度对3求余来判断是否在二进制字符串前面加0。用flag判断八进制的首位是否为零。以三位二进制为一个集合转化为八进制并且直接输出,避免了整个八进制存入数组或string字符串中。

菜鸟一枚,不太会用文字描述。




猜你喜欢

转载自blog.csdn.net/MM_GS/article/details/69486933