蓝桥杯 16-8进制转换问题

世界上最凉的事情是什么呢,是你明明想到了却做不出来
刚刚在做蓝桥杯的练习题,16进制转到8进制
一下子就想到了把16转换成2再转换成8的方法,然后也写出来了,但是只在小的范围内是正确的,自己也不知道是哪里出了问题,十分凉凉
题目如下
问题描述
  给定n个十六进制正整数,输出它们对应的八进制数。

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

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

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

样例输入
  2
  39
  123ABC

样例输出
  71
  4435274

【提示】
  先将十六进制数转换成某进制数,再由某进制数转换成八进制。
我的错误代码

#include<iostream>
#include<string>
#include<stack>
using namespace std;
void toEight(char* b, int n)//2进制转换成8进制
{
	stack<int> s;
	int i;
	for (i = n - 1; i >= 0; i -= 3)
	{
		if (i - 2 >= 0)
		{
			int z = b[i] * 1 + b[i - 1] * 2 + b[i - 2] * 4;
			s.push(z);//入栈,最后输出为正序
		}
		else if (i - 1 >= 0)//最后剩不到3位的2种情况
		{
			int z = b[i] * 1 + b[i - 1] * 2;
			s.push(z);
		}
		else
		{
			int z = b[i];
			s.push(z);
		}
	}
	if (s.top() == 0)
		s.pop();//第一位是0的不输出
	while (!s.empty())
	{
		cout << s.top();//输出转换后的结果
		s.pop();
	}
	cout << endl;
}

void toTwo(string a)
{
	char b[400005];
	for (int i = 0; i<a.size(); i++)
	{
		int j = 4 * i + 3;
		int x;
		if (a[i]>'0'&&a[i] < '9')
			x = a[i] - 48;
		else
			x = a[i] - 55;
		for (int k = 0; k<4; j--, k++)//将16进制转换为2进制
		{
			b[j] = x % 2;
			x /= 2;
		}
	}
	toEight(b, a.size()*4);
}

int main()
{
	string a;
	int n;
	while (cin >> n)
	{
		while (n--)
		{
			cin >> a;
			toTwo(a);
		}
	}
}

此处是别人ac的代码

#include <iostream>  
#include <string.h>  
#include <stack>  
using namespace std;  
  
int fib(int n)//计算2的多少次方  
{  
    int sum=1;  
    if(n==0)  
        return 1;  
    else  
    {  
        for(int i=1;i<=n;i++)  
            sum*=2;  
        return sum;  
    }  
}  
  
string str[11];  
  
int two[400008];//因为16进制的位数不超过100000,所以换成二进制数位数不超过400000  
  
int main()  
{  
    int n,i,j,k;  
    cin>>n;  
    for(int k=1;k<=n;++k)  
    {  
        cin>>str[k];  
        memset(two,0,sizeof(two));  
        for( i=0;i<str[k].length();++i)//把十六进制的每一位变成4个二进制数,注意存放的顺序  
        {  
            if(str[k][i]>='0'&&str[k][i]<='9')  
            {  
                int temp=str[k][i]-'0';  
                int tap=4*(i+1);//把two数组每4个元素为一组,连续,当前的十六进制位为two数组的最大下标+1  
                while(temp)  
                {  
                    two[--tap]=temp%2;//首先要tap-1,因为two数组是从0开始的,这也解释了为什么上面说是最大下标+1  
                    temp/=2;  
                }  
            }  
            else  
            {  
                int temp=str[k][i]-55;//A-55得10  
                int tap=4*(i+1);  
                while(temp)  
                {  
                    two[--tap]=temp%2;  
                    temp/=2;  
                }  
            }  
        }//到目前为止把16进制转成了二进制  
        int count=0;//二进制数三位一组来转化为8进制  
        int sum=0;//连续三位二进制数的值  
        stack<int>q;  
        for(j=4*str[k].length()-1;j>=0;--j)//从two数组的存数的最大下标开始处理,每三个为一组,转化为8进制,保存在栈中  
        {  
            sum+=(two[j]*fib(count++));  
            if(count==3)  
            {  
                q.push(sum);  
                sum=0;  
                count=0;  
            }  
  
        }  
        int sum1=0;//考虑处理的末尾,可能最后一组少于3个,有可能是一个,也可能是两个,单独处理,单独输出  
        int c=0;  
        for(int m=4*str[k].length()%3-1;m>=0;--m)//4*str[k].length()%3判断还剩下几个  
        {  
            sum1+=two[c++]*fib(m);  
        }  
        if(sum1!=0)  
            cout<<sum1;//单独输出  
        if(q.top()==0)  
            q.pop();//去除前导0,如果有的话  
        while(!q.empty())  
        {  
           cout<<q.top();//从栈中输出  
            q.pop();  
        }  
        cout<<endl;  
    }  
    return 0;  
}  

http://blog.csdn.net/sr_19930829/article/details/18677037
(博主的博客)
这个博主的同学还写了一种更简洁的,我觉得很巧妙,感兴趣的可以自己看一下。


哈哈,时隔不久,我就把bug调出来了

#include<iostream>
#include<string>
#include<stack>
using namespace std;
void toEight(string b)
{
	stack<int> s;
	int i;
	if (b.size() % 3 == 1)
		b = "00" + b;
	else if (b.size() % 3 == 2)
		b = '0'+b;
	for (i = b.size() - 1; i >= 0; i -= 3)
	{
		int z = (b[i] - 48) * 1 + (b[i - 1] - 48) * 2 + (b[i - 2] - 48) * 4;
		s.push(z);
	}
	if (s.top() == 0)
		s.pop();
	while (!s.empty())
	{
		cout << s.top();
		s.pop();
	}
	cout << endl;
}

void toTwo(string a)
{
	string b;
	for (int i = 0; i<a.size(); i++)
	{
		b += "0000";
		int j = 4 * i + 3;
		int x;
		if (a[i]>='0'&&a[i] <= '9')
			x = a[i] - 48;
		else
			x = a[i] - 55;
		for (int k = 0; k<4; j--, k++)
		{
			b[j] = x % 2+48;
			x /= 2;
		}
	}
	toEight(b);
}

int main()
{
	string a;
	int n;
	while (cin >> n)
	{
		while (n--)
		{
			cin >> a;
			toTwo(a);
		}
	}
}

嗯就是很开心,感谢绿色的小熊给我的帮助

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值