題目
問題描述
給定n個十六進位正整數,輸出它們對應的八進位數。
輸入格式
輸入的第一行為一個正整數n (1<=n<=10)。
接下來n行,每行一個由09、大寫字母AF組成的字符串,表示要轉換的十六進位正整數,每個十六進位數長度不超過100000。
輸出格式
輸出n行,每行為輸入對應的八進位正整數。
【注意】
輸入的十六進位數不會有前導0,比如012A。
輸出的八進位數也不能有前導0。
樣例輸入
2
39
123ABC
樣例輸出
71
4435274
【提示】
先將十六進位數轉換成某進位數,再由某進位數轉換成八進位。
解答:
該題思路比較簡單,將輸入的若干16進位數轉換為2進位,再將每三位2進位數轉換為一個八進位數即可。需要注意的是輸出的數據首位若為0則不輸出。
但是效率是個大問題,一直「運行超時」。經過以下幾個版本的改進,終於通過了測評。
**題解一:**使用字符數組
這樣做有兩個明顯的缺點:
1、需要為字符數組分配固定空間。
2、插入、取出操作特別麻煩。
#include <iostream>using namespace std;int main(){int n=0;cin>>n;char a[10][100000]; //原數字串,16進位 char b[400000]; //2進位中轉數字串char c[300000]; //8進位目標數字串 //獲取準備轉換的n個數 for(int i=0;i<n;i++){for(int j=0;j<1000;j++){a[i][j]='\n';} cin>>a[i];}int count[10];for(int i=0;i<10;i++)count[i]=0;//轉換 for(int i=0;i<n;i++){//計算出每一個數的長度 for(int j=0;a[i][j]!='\n';j++)count[i]++;count[i]--;//轉換得到2進位數 for(int j=0;j<count[i];j++){ if(a[i][j]<='9'){b[j*4]=(a[i][j]-'0')/8+48;b[j*4+1]=((a[i][j]-'0')%8)/4+48;b[j*4+2]=((a[i][j]-'0')%4)/2+48;b[j*4+3]=((a[i][j]-'0')%2)/1+48;}else{b[j*4]=(a[i][j]-'A'+10)/8+48;b[j*4+1]=((a[i][j]-'A'+10)%8)/4+48;b[j*4+2]=((a[i][j]-'A'+10)%4)/2+48;b[j*4+3]=((a[i][j]-'A'+10)%2)/1+48;}} int y=0;if(count[i]*4%3>0)y=(count[i]*4)/3+1;else if(count[i]*4%3==0)y=(count[i]*3)/4;//轉換得到八進位數 for(int j=count[i]*4-1, m=0; m<y; j=j-3,m++) {//cout<<"轉換得到八進位"<<j<<endl;if(j/3>0)c[m] = (b[j]-'0') + (b[j-1]-'0')*2 + (b[j-2]-'0')*4+48;else if(j-1==0)c[m] = (b[j]-'0') +48;else if(j-2==0)c[m] = (b[j]-'0') + (b[j-1]-'0')*2 + 48; //cout<<"各項為:"<<b[j]<<b[j-1]<<b[j-2]<<" "<<endl;} for(int j=y-1;j>=0;j--){if(j==y-1&&c[j]==48);elsecout<<c[j];}cout<<endl;}return 0; }
;i++){>;i++){for(int>
題解二:**使用字符串String
string提供了更多便捷實用的方法(如substr()截取字符串的某段、insert()在某個位置插入一段字符串、length()獲取該字符串的長度等等),同時也避免了第一版代碼所出現的問題。
但是仍然運行超時,說明這兩個版本的代碼存在著共同的問題,那麼就肯定是進位轉換時做了太多無用的計算了——每一步我們都將ASCII碼轉換為整形數據,再用數學的方法計算出2/8進位數。
#include <iostream>#include <string>using namespace std;int main(){int n=0; //記錄輸入數據的個數 cin>>n;string sixTeen[10]; //用來記錄輸入的數據 for(int i=0;i<n;i++){cin>>sixTeen[i];}string eight;//記錄八進位數據 char eig;for(int i=0;i<n;i++){ string tow; //記錄二進位數據 //轉換為二進位 for(int j=0;j<sixTeen[i].length();j++){if(sixTeen[i][j]<='9'){int now=sixTeen[i][j]-'0'; //由字符串的ASCII碼得到數值 eig=now/8+'0';tow=tow+eig; //對數值做計算並且再轉換回ASCII碼存入字符串 eig=now%8/4+'0';tow=tow+eig; eig=now%4/2+'0';tow=tow+eig; eig=now%2+'0';tow=tow+eig; }else{int now=sixTeen[i][j]-'A'+10;eig=now/8+'0';tow=tow+eig; //對數值做計算並且再轉換回ASCII碼存入字符串 eig=now%8/4+'0';tow=tow+eig; eig=now%4/2+'0';tow=tow+eig; eig=now%2+'0';tow=tow+eig; }}//cout<<tow<<endl; //轉換為八進位//首先補齊「0」 int m=tow.length()%3;if(m==1)tow.insert(0,"00");else if(m==2)tow.insert(0,"0");//進行轉換 for(int k=0;k<tow.length()/3;k++){eig=(tow[k*3]-'0')*4+(tow[k*3+1]-'0')*2+(tow[k*3+2]);eight=eight+eig;} //輸出最終的八進位數 cout<<eight<<endl;}return 0;}
;i++){cin>
**題解三:**使用Switch語句枚舉
考慮到我們操作的對象只有字符串,16進位轉2進位只用16種情況,而2進位轉8進位也只有8種情況,所以只需要枚舉所有情況即可。這樣就可以避免坂本一、二代碼共同的問題。
#include <iostream>using namespace std;int main(){int n=0; //記錄輸入數據的個數 cin>>n;string sixTeen[10]; //用來記錄輸入的數據 for(int i=0;i<n;i++){cin>>sixTeen[i];} for(int i=0;i<n;i++){string eight;//記錄八進位數據string tow; //記錄二進位數據 char eig;//轉換為二進位 for(int j=0;j<sixTeen[i].length();j++){switch(sixTeen[i][j]){case '0':tow+="0000";break; case '1':tow+="0001";break; case '2':tow+="0010";break; case '3':tow+="0011";break; case '4':tow+="0100";break; case '5':tow+="0101";break; case '6':tow+="0110";break; case '7':tow+="0111";break; case '8':tow+="1000";break; case '9':tow+="1001";break; case 'A':tow+="1010";break; case 'B':tow+="1011";break; case 'C':tow+="1100";break; case 'D':tow+="1101";break; case 'E':tow+="1110";break; case 'F':tow+="1111";break; default:break; }}//轉換為八進位//首先補齊「0」 int m=tow.length()%3;if(m==1)tow.insert(0,"00");else if(m==2)tow.insert(0,"0");//進行轉換 if(!(tow[0]=='0'&&tow[1]=='0'&&tow[2]=='0')){eig=(tow[0]-'0')*4+(tow[1]-'0')*2+(tow[2]);eight=eight+eig;}for(int k=3;k<tow.length();k=k+3){//eig=(tow[k*3]-'0')*4+(tow[k*3+1]-'0')*2+(tow[k*3+2]);//eight=eight+eig;if(tow.substr(k,3)=="000")eight+="0";else if(tow.substr(k,3)=="001")eight+="1";else if(tow.substr(k,3)=="010")eight+="2";else if(tow.substr(k,3)=="011")eight+="3";else if(tow.substr(k,3)=="100")eight+="4"; else if(tow.substr(k,3)=="101")eight+="5"; else if(tow.substr(k,3)=="110")eight+="6"; else if(tow.substr(k,3)=="111")eight+="7"; }//輸出最終的八進位數 cout<<eight<<endl;}return 0;}