前言
传送门
起初想先将16进制转为10进制再转为8进制,发现题目中16进制数长度可达100000,即使是long long类型,范围也没那么大,于是准备将16进制转为2进制,再将2进制转为8进制。
16进制转2进制,就每一位16进制数转为4位2进制数即可,用一个string变量存储转换后的2进制数,再对这个string变量,每三位做一组,转换为一位8进制数即可,值得注意的是题目要求输出的8进制不能有前导0,因此需要判断一下,如果前导为0,就不要输出前导0了
正文
问题描述
给定n个十六进制正整数,输出它们对应的八进制数。
输入格式
输入的第一行为一个正整数n (1<=n<=10)。
接下来n行,每行一个由0~9、大写字母A~F组成的字符串,表示要转换的十六进制正整数,每个十六进制数长度不超过100000。
输出格式
输出n行,每行为输入对应的八进制正整数。
【注意】
输入的十六进制数不会有前导0,比如012A。
输出的八进制数也不能有前导0。
样例输入
2
39
123ABC
样例输出
71
4435274
【提示】
先将十六进制数转换成某进制数,再由某进制数转换成八进制。
AC代码
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
using namespace std;
//16进制转8进制
void convert(){
string str,str2,res;
cin>>str;
int len=str.length(),x;
//16进制转为2进制 ,存储到str2中
for(int i=0;i<len;i++){
switch(str[i]){
case '0':str2 += "0000"; break;
case '1':str2 += "0001"; break;
case '2':str2 += "0010"; break;
case '3':str2 += "0011"; break;
case '4':str2 += "0100"; break;
case '5':str2 += "0101"; break;
case '6':str2 += "0110"; break;
case '7':str2 += "0111"; break;
case '8':str2 += "1000"; break;
case '9':str2 += "1001"; break;
case 'A':str2 += "1010"; break;
case 'B':str2 += "1011"; break;
case 'C':str2 += "1100"; break;
case 'D':str2 += "1101"; break;
case 'E':str2 += "1110"; break;
case 'F':str2 += "1111"; break;
}
}
//除以3后的余数 ,x表示次方 ,8进制由三位二进制表示,三位的权重分别为 2^2,2^1,2^0;
int remain=str2.length()%3;
if(remain==0) x=2;
else if(remain==1)x=0;
else if(remain==2)x=1;
int tempNum=0;
//二进制转8进制,注意题目要求输出的8进制不能有前导0
bool isZero=false;
for(int i=0;i<str2.length();i++){
tempNum+=(str2[i]-'0')*pow(2,x);//字符转数字
x--;
if(x==-1){
x=2;
//前导为0,此时continue跳过本次循环,去除前导0
if(isZero==false&&tempNum==0){
tempNum=0;
isZero=true;
continue;
}
//前导不为0,后面就不用判断了,故设置isZero为真
if(isZero==false)isZero=true;
res+=(tempNum+'0');//数字转字符串
tempNum=0;
}
}
cout<<res<<endl;
}
int main(){
int n;
scanf("%d",&n);
while(n--){
convert();
}
return 0;
}
后记
经历27天的域名备案终于好了,真不知踩了多少坑,下面是结合GitHub上一个开源的视频播放器做的一个小demo——>https://www.inzc.top/nzc/finalWork/test/