世界上最凉的事情是什么呢,是你明明想到了却做不出来
刚刚在做蓝桥杯的练习题,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);
}
}
}
嗯就是很开心,感谢绿色的小熊给我的帮助