前言
傳送門
起初想先將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/