問題描述
給定n個十六進制正整數,輸出它們對應的八進制數。
輸入格式
輸入的第一行為一個正整數n (1<=n<=10)。
接下來n行,每行一個由0~9、大寫字母A~F組成的字元串,表示要轉換的十六進制正整數,每個十六進制數長度不超過100000。
輸出格式
輸出n行,每行為輸入對應的八進制正整數。
【注意】
輸入的十六進制數不會有前導0,比如012A。
輸出的八進制數也不能有前導0。
樣例輸入
2
39
123ABC
樣例輸出
71
4435274
【提示】
先将十六進制數轉換成某進制數,再由某進制數轉換成八進制。
思路:
首先,因為題設16進制字元串的長度極其龐大(n<=100000),在之前的題目中可以使用标準庫函數幾行結束的方法在這體中不可行(long long都無法完整儲存下這個字元串)。是以,隻能自己通過處理字元串的方式來解決。
可以注意到,題設為16進制->8進制,皆為2的指數倍,是以可以将單個16進制數轉化為4個2進制儲存,然後再3個一組将其轉化為8進制。但是需要注意,這樣我們需要将轉化為2進制的字元串長度補全為3的倍數。
代碼如下
#include <bits/stdc++.h>
using namespace std;
string ToBin(void) {//擷取16進制字元串,同時直接将其轉化為2進制
string s;
char c;
while (!isspace(c = getchar())) {
switch (c) {
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;
default: break;
}
}
//将字元串補全為3的整數倍
if (s.length() % 3 == 2)
s = "0" + s;
else if (s.length() % 3 == 1)
s = "00" + s;
/
return s;
}
string ToOct(string bin) {
string oct;
for (int i = 0; i <= bin.length() - 3; i += 3) {//三個一組将其轉化為8進制
string sub = bin.substr(i, 3);
char *t;
// int n = stoi(sub, 0, 2);//藍橋杯的編譯器似乎預設不開啟C++11的支援,隻能使用下面的代替
int n = strtol(sub.c_str(), &t, 2);
if (n == 0) {
if (i != 0)
oct += '0';
} else {
oct += '0' + n;
}
}
return oct;
}
int main(void) {
// freopen("input.txt", "r", stdin);
// freopen("BASIC-12.txt", "w", stdout);
int n;
scanf("%d\n", &n);//因為在ToBin()中需要對單個字元進行處理,此處不能遺忘'\n'
while (n--) {
string bin = ToBin();
string oct = ToOct(bin);
cout << oct << endl;
}
}