1. 程式人生 > >BASIC-12十六進位制轉換為八進位制

BASIC-12十六進位制轉換為八進位制

題目
問題描述
  給定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) ; else cout<<c[j]; } cout<<endl; } return 0; }

題解二:**使用字串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;
}

**題解三:**使用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;
}