本文運用DEVC++軟件,通過C++類的定義和重載運算符來實現十六進制數類的運算操作,代碼以單文件的方式來構建。
題目描述如下:
設計1~4位的無符號十六進制數據類class HEX. 可以創建如 ABCD、1234、DF09、AB、26之類的1~4位的十六進制的正整數。可以輸入輸出十六進制數據,可以實現十六進制數據和十進制數據的互換,可以實現2個十六進制數據的+、-、*、/、%操作。
爲實現上述目的,我們首先來構建主函數,在主函數的構建中,我們自然希望操作界面簡潔友好,希望將十進制數的加減乘除操作自然而然的轉移到十六進制數上,使輸入輸出一目瞭然,因而在後續的類的定義上要下一番功夫,也要用到運算符的重載。
int main()
{ HEX n1,n2,n3;
char repeat('Y');
do
{ n1 = 0; n2 = 0; n3 =0;
cin>>n1>>n2; //n1,n2爲十六進制數
n3 = n1+n2;
cout<<n1<<'+'<<n2<<'='<<n3<<endl;
n3 = n1-n2;
cout<<n1<<'-'<<n2<<'='<<n3<<endl;
n3 = n1*n2;
cout<<n1<<'*'<<n2<<'='<<n3<<endl;
n3 = n1/n2;
cout<<n1<<'/'<<n2<<'='<<n3<<endl;
n3 = n1%n2;
cout<<n1<<'%'<<n2<<'='<<n3<<endl;
cout<<"Repeat?(Y/N)";
cin>>repeat;
}while(repeat=='Y'||repeat=='y');
return 0;
}
由上面的主函數代碼可以看到,加減乘除的命令符號沿用了十進制數的加減乘除,因而要對這些運算符在十六進制數類的範圍下重載。此外,主函數設置了循環,只是爲了方便重複測試。
下面來定義十六進制數類以及類的各種操作。特別要注意的一點是,因爲在輸入輸出十六進制數時要訪問類的成員,因而要在重載輸入輸出符時將其設置爲友元。
#include <iostream>
#include <string>
#include <cmath>
#include <process.h>
using namespace std;
char Hex_num[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; //十六進制數字符的取值範圍,便於後續的轉化操作
class HEX
{ char m_num[10]; //可以存放10位十六進制數據,這樣可以確保2個4位十六進制數據+和*的結果不會溢出
public:
HEX(); //構造函數,初始化成全‘0’
HEX(unsigned n); //用無符號整數創建十六進制數據,(即無符號整數轉換成十六進制數據)
unsigned GetBit(int i); //獲得每一位數據的十進制數值
operator unsigned(); //把十六進制數據轉換成無符號的十進制數據
int length(); //獲得數據的長度
HEX operator+(HEX n); //加法
HEX operator-(HEX n); //減法運算要求被減數不小於減數
HEX operator*(HEX n); //乘法
HEX operator/(HEX n); //整除,即只要得到商
HEX operator%(HEX n); //取模,即只要得到餘數
HEX& operator++(); //前置++
HEX operator++(int); //後置++
friend istream & operator>>(istream &i, HEX& n);
// 輸入十六進制數
friend ostream & operator<<(ostream &o, HEX n);//輸出十六進制數
};
上面只是類的申明,尤其是對運算只給出了一個基本框架,還須具體實現它,接下來就是對其的具體補充。
(1)默認構造函數
HEX::HEX()
{ memset(m_num,'0',sizeof(m_num));
}
(2) 重載構造函數,將十進制數轉成十六進制數並以逆序存儲
HEX::HEX(unsigned n) //十六進制數字符以逆序存儲,並以'\0'字符結束
{
HEX();
int i=0,t,j=0;
if(n>0) //處理n>0的情況
while (n >0)
{
t=n%16;
m_num[i++]= Hex_num[t];
n = n / 16;
}
else m_num[i++]='0'; //處理n=0的情況
m_num[i]='\0';
}
(3)獲取每一位字符的十進制數值。主要思路,對讀取的字符分兩種情況處理,一種是A~F,一種是0~9,用其與A或0字符將字符轉成數值,再根據所在位數(k),用
unsigned HEX::GetBit(int i) //從十六進制數的最低位算起,獲取第i位數的十進制表示
{
int a;
if(m_num[i-1]>='A'&&m_num[i-1]<='F')
a=m_num[i-1]-'A'+10;
else
a=m_num[i-1]-'0';
while(i>1)
{
a=a*16;
i--;
}
return a;
}
(4)利用GetBit(i)實現把十六進制數據轉換成無符號的十進制數據
HEX::operator unsigned()
{
int j=1;
int b=0;
for(;j<=10&&m_num[j-1]!='\0';j++) //判斷字符是否結束
b+=GetBit(j);
return b;
}
(5)獲得十六進制數的長度
int HEX::length()
{ return strlen(m_num);}
(6)重載‘+’運算符。對加減乘除運算符的重載主要是通過當前指針this和類型轉換來實現的,即首先定義兩個無符號整數變量a,b,然後通過類型轉換將十六進制數轉成十進制數,隨後進行加減乘除運算,最後再通過調用構造函數把結果的數據類型轉成十六進制。
這裏之所以能夠實現類型轉換是因爲前面定義了類型轉換(4)HEX:: operator unsigned.
HEX HEX::operator+(HEX n) //利用類型轉換實現四則運算
{
unsigned a,b;
a=*this;
b=n;
return HEX(a+b);
}
(7)‘-’運算符重載。想法與加法運算符重載基本一致,但是需要注意的是要先判斷被減數是否大於減數,若大於則進行減法運算,反之報錯。
HEX HEX::operator-(HEX n)
{
unsigned a,b;
a=*this;
b=n;
if(a<b)
cout<<"錯誤:被減數小於減數"<<endl;
else
return HEX(a-b);
}
(8)‘*’,’/’,’%’運算符重載是平凡的,與加法是完全一致的,因而此處略去代碼。
(9)實現前置++。想法是通過類型轉換和this指針來實現。
HEX& HEX::operator++()
{
unsigned a=*this;
*this=HEX(a+1);
return (*this);
}
(10)實現後置++
HEX HEX::operator++(int)
{
HEX old=*this;
++(*this);
return old;
}
(11)實現十六進制數的輸入。由於十六進制數以逆序存儲,所以輸入數據時對其反轉,並以’\0’字符結束 。
istream& operator>>(istream& i, HEX& n)
{
cout<<"Please input a Hex number(>=0,<=FFFF,Hex characters:0-9 or A-F):"<<endl;
char temp[10];
i>>temp;
int len=strlen(temp); //調用取長函數來尋找初始存儲位置
int j;
for(j=0;j<len;j++)
n.m_num[j]=temp[len-1-j];
n.m_num[j]='\0';
return i;
}
(12)實現十六進制數的輸出。與輸入類似,由於十六進制數以逆序存儲,所以輸出數據逆序輸出。
ostream& operator<<(ostream& o, HEX n)
{
int len=n.length();
int j;
for(j=0;j<len;j++)
o<<n.m_num[len-j-1];
return o;
}
結語:
到這裏就結束啦,回顧一下,其實通過重載運算符實現十六進制數的運算的關鍵在於運用類型轉換和this指針,還有就是要清楚自己所定義的十六進制數在計算機中存儲的方式,本文采用的逆序存儲,其實也可以採用順序存儲啦,只要自己清楚其存儲方式,在用字符的時候不要搞錯了就好啦。
完整的代碼我也會上傳供大家參考,這個是單文件的,後續會補一個多文件的。
http://download.csdn.net/detail/zhazhazl/9645690
代碼的測試輸出如下: