MOOC清华《面向对象程序设计》第5章:填充数字矩阵-终极中文版 v 3.0(采用模板方法,并增加集中控制功能)
2017-09-03 09:34
411 查看
//main.cpp #include <iostream> #include <cstring> #include "Matrix.h" using namespace std; const int str_length = 7;//经测试,至少为7;印证了每个汉字占2个字节('\0'占一个字节) int main() { int size; char style[str_length]; char key_point[str_length]; cout << "请输入矩阵的边长 N: "; cin >> size; cout << "请输入填充方式(顺时针、逆时针、行优先、列优先): "; cin >> style; cout << "请输入从哪一个角开始填充(左上角、左下角、右上角、右下角): "; cin >> key_point; void fill_style(int size, char* str1, char* str2); fill_style(size, style, key_point); return 0; } void fill_style(int size, char* str1, char* str2){ if(strcmp(str1, "顺时针") == 0){ ClockwiseMatrix obj(size); if(strcmp(str2, "左上角") == 0){ obj.row = 0; obj.col = -1; obj.dir = 'R'; obj.fill(); cout << obj; } if(strcmp(str2, "右上角") == 0){ obj.row = -1; obj.col = size - 1; obj.dir = 'D'; obj.fill(); cout << obj; } if(strcmp(str2, "右下角") == 0){ obj.row = size - 1; obj.col = size; obj.dir = 'L'; obj.fill(); cout << obj; } if(strcmp(str2, "左下角") == 0){ obj.row = size; obj.col = 0; obj.dir = 'U'; obj.fill(); cout << obj; } } if(strcmp(str1, "逆时针") == 0){ AnticlockMatrix obj(size); if(strcmp(str2, "左上角") == 0){ obj.row = -1; obj.col = 0; obj.dir = 'D'; obj.fill(); cout << obj; } if(strcmp(str2, "左下角") == 0){ obj.row = size - 1; obj.col = -1; obj.dir = 'R'; obj.fill(); cout << obj; } if(strcmp(str2, "右下角") == 0){ obj.row = size; obj.col = size - 1; obj.dir = 'U'; obj.fill(); cout << obj; } if(strcmp(str2, "右上角") == 0){ obj.row = 0; obj.col = size; obj.dir = 'L'; obj.fill(); cout << obj; } } if(strcmp(str1, "行优先") == 0){ RowFirstMatrix obj(size); if(strcmp(str2, "左上角") == 0){ obj.row = 0; obj.col = -1; obj.dir = 'D'; obj.fill(); cout << obj; } if(strcmp(str2, "右上角") == 0){ obj.row = 0; obj.col = size; obj.dir = 'L'; obj.fill(); cout << obj; } if(strcmp(str2, "左下角") == 0){ obj.row = size - 1; obj.col = -1; obj.dir = 'R'; obj.fill(); cout << obj; } if(strcmp(str2, "右下角") == 0){ obj.row = size - 1; obj.col = size; obj.dir = 'U'; obj.fill(); cout << obj; } } if(strcmp(str1, "列优先") == 0){ ColFirstMatrix obj(size); if(strcmp(str2, "左上角") == 0){ obj.row = -1; obj.col = 0; obj.dir = 'D'; obj.fill(); cout << obj; } if(strcmp(str2, "右上角") == 0){ obj.row = -1; obj.col = size - 1; obj.dir = 'L'; obj.fill() 4000 ; cout << obj; } if(strcmp(str2, "左下角") == 0){ obj.row = size; obj.col = 0; obj.dir = 'R'; obj.fill(); cout << obj; } if(strcmp(str2, "右下角") == 0){ obj.row = size; obj.col = size - 1; obj.dir = 'U'; obj.fill(); cout << obj; } } }
//Matrix.h #ifndef Matrix_h #define Matrix_h #include <iostream> using namespace std; class Matrix{ public: int _size;//方阵的规模 int *_data;//数据空间 int row, col; char dir;//用于顺时针、逆时针、行优先、列优先时的方向判定 Matrix(int size); ~Matrix(); void fill(); virtual int findPosition() = 0; int fill_style(char* str1, char* str2); friend ostream& operator<< (ostream& out, const Matrix& m); }; class ClockwiseMatrix:public Matrix{ public: using Matrix::Matrix; int findPosition();//顺时针辅助函数 }; class AnticlockMatrix:public Matrix{ public: using Matrix::Matrix; int findPosition();//逆时针辅助函数 }; class RowFirstMatrix:public Matrix{ public: using Matrix::Matrix; int findPosition();//行优先辅助函数 }; class ColFirstMatrix:public Matrix{ public: using Matrix::Matrix; int findPosition();//列优先辅助函数 }; #endif
//Matrix.cpp #include <iostream> #include <cstring> #include "Matrix.h" using namespace std; Matrix::Matrix(int size): _size(size) { _data = new int[size * size]; memset(_data, 0, sizeof(int) * _size * _size); } Matrix::~Matrix(){ delete _data; } ostream& operator<< (ostream& out, const Matrix& m){ for(int r = 0; r < m._size; r++){ //row for(int c = 0; c < m._size; c++) //col cout << *(m._data + r * m._size + c) << '\t'; cout << endl; } } void Matrix::fill(){ for(int num = 1; num <= _size * _size; num++){ int pos = findPosition(); _data[pos] = num; } }
//ClockwiseMatrix.cpp #include <iostream> #include "Matrix.h" using namespace std; int ClockwiseMatrix::findPosition(){ switch(dir){ case 'D': if(row < _size - 1 && _data[(row + 1) * _size + col] == 0) row++; else{ dir = 'L'; // next direction col--; } break; case 'L': if(col > 0 && _data[row * _size + col - 1] == 0) col--; else{ dir = 'U'; // next direction row--; } break; case 'U': if(row > 0 && _data[(row - 1) * _size + col] == 0) row--; else{ dir = 'R'; // next direction col++; } break; case 'R': if(col < _size - 1 && _data[row * _size + col + 1] == 0) col++; else{ dir = 'D'; // next direction row++; } break; } return row * _size + col; }
//AnticlockMatrix.cpp #include <iostream> #include "Matrix.h" using namespace std; int AnticlockMatrix::findPosition(){ switch(dir){ case 'D': if(row < _size - 1 && _data[(row + 1) * _size + col] == 0) row++; else{ dir = 'R'; // next direction col++; } break; case 'R': if(col < _size - 1 && _data[row * _size + col + 1] == 0) col++; else{ dir = 'U'; // next direction row--; } break; case 'U': if(row > 0 && _data[(row - 1) * _size + col] == 0) row--; else{ dir = 'L'; // next direction col--; } break; case 'L': if(col > 0 && _data[row * _size + col - 1] == 0) col--; else{ dir = 'D'; // next direction row++; } break; } return row * _size + col; }
//RowFirstMatrix.cpp #include <iostream> #include "Matrix.h" using namespace std; int RowFirstMatrix::findPosition(){ switch(dir){ case 'D'://行优先且向右且向下填充(左上角) if(col < _size - 1 && _data[row * _size + col + 1] == 0) col++; else if(row < _size - 1){ row++; col = 0; } break; case 'L'://行优先且向左且向下填充(右上角) if(col > 0 && _data[row * _size + col - 1] == 0) col--; else if(row < _size - 1){ row++; col = _size - 1; } break; case 'R'://行优先且向右且向上填充(左下角) if(col < _size - 1 && _data[row * _size + col + 1] == 0) col++; else if(row > 0){ row--; col = 0; } break; case 'U'://行优先且向左且向上填充(右下角) if(col > 0 && _data[row * _size + col - 1] == 0) col--; else if(row > 0){ row--; col = _size - 1; } break; } return row * _size + col; }
//ColFirstMatrix.cpp #include <iostream> #include "Matrix.h" using namespace std; int ColFirstMatrix::findPosition(){ switch(dir){ case 'D'://列优先且向下且向右填充(左上角) if(row < _size - 1 && _data[(row + 1) * _size + col] == 0) row++; else if(col < _size - 1){ col++; row = 0; } break; case 'L'://列优先且向下且向左填充(右上角) if(row < _size - 1 && _data[(row + 1) * _size + col] == 0) row++; else if(col > 0){ col--; row = 0; } break; case 'R'://列优先且向上且向右填充(左下角) if(row > 0 && _data[(row - 1) * _size + col] == 0) row--; else if(col < _size - 1){ col++; row = _size - 1; } break; case 'U'://列优先且向上且向左填充(右下角) if(row > 0 && _data[(row - 1) * _size + col] == 0) row--; else if(col > 0){ col--; row = _size - 1; } break; } return row * _size + col; }
全方位无死角测试:
【顺时针】
【逆时针】
【行优先】
【列优先】
调试成功的经验:
把之前Debug日志中的Style类换成main文件中一个普通函数,然后分别实例化四个派生类,分别传参数,分别调用填充函数fill()(同时自动调用各自的findPosition()),分别输出结果——一切搞定。
什么样的功能适合用派生类实现,什么样的功能适合用普通函数实现,什么样的功能适合放在main文件中……这些都是需要考虑的:既要全盘考虑各个功能、接口之间的关系,又要考虑每个功能、每个接口的实现细节。作为一个独立开发者、未来的创业公司CEO,务必有这种能力。
至于派生类与基类之间的构造函数和各个成员的调用关系,还需要在回顾代码的过程中仔细体会。已经得到的基本认识就是:派生类using基类的构造函数,若带参数,则直接初始化了基类的相应参数(比如_size)。如果这个参数是公有的,则派生类本身继承来的这个参数也得到了初始化;如果这个参数是私有的,则派生类并没有继承它,也就不存在初始化这个参数一说。而派生类的其他继承自基类的公有成员,若被赋值,则只停留在派生类这一级的成员,并不会“上传”至基类的成员。
最重要的一条经验还是:不要把两个平级的派生类搅和在一起,否则会跟goto语句一样地引起逻辑混乱,不易理解。所以说,虽然是面向对象程序设计了,但是依然要遵循流程化的设计思想,不同的流程分支互相不干涉,这样设计出的程序才既干净又清晰。所谓软件工程要力图避免的软件危机现象,我认为其实就是团队中不同的人之间在程序设计的逻辑思维上存在这样或那样的偏差,从而引起了混乱。用《人月神话》中的话说,就像一头巨兽掉进了泥潭,越挣扎陷得越深。从昨天中午到今天早上,我就感觉自己是那头巨兽。一个人独立编程都会出现软件危机的情况,多人尤其是很多人的时候当然更加容易出现。
作为一个计算机和软件的初学者,上述观点也许片面,但是是我的真实感受。希望今后继续提高。
相关文章推荐
- MOOC清华《面向对象程序设计》第5章:OOP版填充数字矩阵(采用模板方法)
- MOOC清华《面向对象程序设计》第5章:OOP版填充数字旋转矩阵-产品级!-终极中文版!
- MOOC清华《程序设计基础》第5章:数字旋转方阵的填充-算法二
- MOOC清华《面向对象程序设计》第7章:负载监视器的设计v2.0(采用基于模板的策略模式)
- MOOC清华《面向对象程序设计》第7章:统计考试及格率v1.0(采用迭代器模式)
- MOOC清华《程序设计基础》第5章:N皇后问题(带矩阵输出)
- MOOC清华《面向对象程序设计》第5章:OOP版填充数字旋转矩阵
- linux采用编译内核的方法增加系统功能调用
- MOOC清华《面向对象程序设计》第5章:OOP版谁做的好事
- MOOC清华《面向对象程序设计》第4章:函数模板的特化实验
- MOOC清华《面向对象程序设计》第8章:邮件过滤器基本框架(采用责任链模式)
- MOOC清华《面向对象程序设计》第8章:栈的实现(采用适配器模式)
- linux采用编译内核的方法增加系统功能调用
- MOOC清华《面向对象程序设计》第5章:OOP版电子计价器
- MOOC清华《面向对象程序设计》第7章:统计考试及格率v5.3(采用函数对象)
- highestAvailable比较灵活,毕竟大多数功能不需要系统最高权限(四种方法:屏蔽UAC,右键以管理员身份运行,增加manisfest,制作数字证书)
- MOOC清华《面向对象程序设计》第8章:栈的实现(采用模板实例化)
- MOOC清华《面向对象程序设计》第4章:类模板的特化实验
- MOOC清华《面向对象程序设计》第4章:函数模板实验
- linux采用编译内核的方法增加系统功能调用