继承实例(进制转换)
来源:互联网 发布:淘宝网卧室台灯 编辑:程序博客网 时间:2024/06/05 18:28
定义一个任意进制的数Number类,继承自string类:
Number类的数据成员:
_radix表示数的基数,
_inum表示数的相应的十进制数
用string存储任意进制的数(可以说是用字符串来存,r进制的数不适合用int来存)
/*Number类的数据成员:_radix表示数的基数,_inum表示数的相应的十进制数*/// more: http://msdn.microsoft.com/en-us/library/0heszx3w.aspx#include <iostream>#include <string>#include <algorithm>using namespace std;class Number : public string {public:Number(string str = "", unsigned int radix = 0, int inum = 0): string(str), _radix(radix) ,_inum(inum) {}void set(unsigned int radix);void strtoi(void);void itostr(void);Number operator+(const Number &);private:unsigned int _radix;int _inum;// 该数的十进制表示};void Number::set(unsigned int radix){_radix = radix;strtoi();// 字符串一但改变,_inum马上变,与+无关// 哪个属性更新了,就马上调用相应的方法以随时保持一致}void Number::itostr(void)// 十进制到r进制:除k取余法{Number &str = *this;if(_inum == 0) {str.push_back('0');}else {int balance = 0;for(int i = 0; _inum > 0; i++) {balance = _inum % _radix;// 注意十六进制str.push_back(balance + (balance < 10 ? '0' : 'A' - 10));_inum /= _radix;}reverse(str.begin(), str.end());}}void Number::strtoi(void)// r进制到十进制:秦九韶算法{const Number &str = *this;if ('0' <= str[0] && str[0] <= (min((int)'9', (int)('0' + _radix - 1))))_inum = str[0] - '0';else if ('A' <= str[0] && str[0] <= 'Z')// 注意十六进制,以下待合法性检查_inum = 10 + str[0] - 'A';else {cout << "Input Error!" << endl;return ;} // 秦九韶算法中的第一个数for (unsigned int i = 1; i < str.length(); i++) {if ('0' <= str[i] && str[i] <= '9')_inum = (_inum * _radix) + str[i] - '0';else if ('A' <= str[i] && str[i] <= 'Z')_inum = (_inum * _radix) + 10 + str[i] - 'A';else {cout << "Input Error!" << endl;return ;}}}Number Number::operator+(const Number &b){Number sum;Number &a = *this;if(a._radix != b._radix) {cerr << "a与b的基数不相等!" << endl;exit(-1);}sum._radix = a._radix;sum._inum = a._inum + b._inum;sum.itostr();// 紧跟_inum的变化调用return sum;//return IToA(AToI(a) + AToI(b), a.radix());}int main(void){Number a, b;int radix;while (cin >> radix && radix >= 2) {cin >> a >> b;// set前必须输入a与b,要初始化(见set函数),这同时也是一个缺陷,待改进a.set(radix);b.set(radix);// 这两句最好到构造函数中去(封装起来?),待改进Number c = a + b;cout << a << " + " << b << " = " << c << endl << endl;}return 0;}
运行结果如下(依次输入基数,第一个数,第二个数):
为什么说继承方便呢?你是否注意到输入a,b时竟然可以直接cin,cout,在itostr函数中用了push_back等string类的成员函数,及在strtoi函数中也用了[ ]运算符,这些其实都是string类中的成员函数(包括标准输入输出的>>与<<),Number类公有继承了string类,都可以直接拿来用了,挺方便!
这里的Number类中只重载了+,当然可以类比地重载-, *, /,这里我就不多写了。
其实在此之前我写了几个版本,比如没使用_inum作为数的属性,重载+、进制转换函数是作为全局函数的。而现在写的版本基本符合一个封装了。
启示:为什么定义类时往往不把属性设为公有的,其中的原因是为了安全性。而我从这篇博客得到了另一点原因,在继承时也使结构更清晰(猜想),我对C++的string类的内部也不是很了解,看源码没找到string类的数据成员,其实string类也是从其它类继承来的。
附:之前的一个版本
// 进制互转运算,十进制数用int表示,其他进制数用Number表示// http://msdn.microsoft.com/en-us/library/0heszx3w.aspx#include <iostream>#include <string>#include <cassert>#include <algorithm>using namespace std;class Number : public string {unsigned int _radix;public:Number(string str = "", int r = 0) : string(str), _radix(r) {}Number operator+(const Number &);Number operator-(const Number &);Number operator*(const Number &);Number operator/(const Number &);void set(unsigned int r) {_radix = r;}unsigned int radix(void) const {return _radix;}};Number IToA(int inum, int radix);// 必须在这声明int AToI(Number str);Number Number::operator+(const Number &b){const Number &a = *this;assert(a.radix() == b.radix());return IToA(AToI(a) + AToI(b), a.radix());}Number Number::operator-(const Number &b){const Number &a = *this;assert(a.radix() == b.radix());return IToA(AToI(a) - AToI(b), a.radix());}Number Number::operator*(const Number &b){const Number &a = *this;assert(a.radix() == b.radix());return IToA(AToI(a) * AToI(b), a.radix());}Number Number::operator/(const Number &b){const Number &a = *this;assert(a.radix() == b.radix());return IToA(AToI(a) / AToI(b), a.radix());}Number IToA(int inum, int radix){Number str;if(inum == 0) {str.push_back('0');}else {int balance = 0;for(int i = 0; inum > 0; i++) {balance = inum % radix;str.push_back(balance + (balance < 10 ? '0' : 'A' - 10));inum /= radix;}reverse(str.begin(), str.end());}return str;}int AToI(Number str){int inum = (str[0] < 'A' ? str[0] - '0' : 10 + str[0] - 'A');// 可加强检查合法性for (unsigned int i = 1; i < str.length(); i++) {inum = (inum * str.radix()) + (str[i] < 'A' ? str[i] - '0' : 10 + str[i] - 'A');}return inum;}/*// 早期版本Number operator*(Number a, Number b){assert(a.radix() == b.radix());return IToA(AToI(a) * AToI(b), a.radix());}*/int main(void){Number a, b;int radix;while (cin >> a >> b >> radix) {assert(radix >= 2);a.set(radix);b.set(radix);cout << a << " + " << b << " = " << a + b << endl<< a << " - " << b << " = " << a - b << endl<< a << " * " << b << " = " << a * b << endl<< a << " / " << b << " = " << a / b << endl << endl;}return 0;}
2012/7/29
其实关于r进制的那些字符(0123456789ABCDEF)用个哈希挺不错(参考自:http://www.cnblogs.com/applebunny/archive/2012/06/21/2557361.html):
const char a[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
避免繁杂的ANSII码计算
2013/4/5
现在看这篇博客,其实设计是不对的,string类和Number类不是继承关系,原来只是为了方便而借用了string类的成员方法。应该用类的组合来实现。
- 继承实例(进制转换)
- C实例---进制转换(栈实现)
- C++私有继承派生类转换成基类引用实例
- c++继承实例(转载)
- 继承实例
- 继承实例
- 继承实例
- JavaScript基础之继承(附实例)
- C++编程实例-继承(一)
- C++编程实例-继承(二)
- Maven中的继承实例(上)
- Maven中的继承实例(下)
- 面向对象程序设计(多态、转换、继承)
- 一起talk C栗子吧(第七回:C语言实例--进制转换)
- 栈的应用实例之——进制转换
- [Java]进制转换代码实例·初级
- 【c++】实例演示类继承中派生类到基类的转换及虚函数
- C++转换与继承;友元friend与继承;静态成员与继承(六)
- Java mail发送邮件
- 魔兽私服TrinityCore 运行调试流程
- JDBC访问数据库的步骤
- xetex用中文写“世界,你好!”
- 操作系统类型(上篇)
- 继承实例(进制转换)
- 随机抽取人员回答问题FLASH
- Java mail接收邮件 回复邮件 转发邮件
- BP算法及例子
- poj 1101 The Game
- 编程之美2.8——找符合条件的整数
- 如何设置WP7 bing地图显示中文
- ACM/ICPC 2011 Asia-Amritapuri Site / B Save the Students!(判断点在三角形中)
- 52个小技巧让WP手机使用更顺手