这是矩阵类的一个简单实现,里面主要运用了运算符重载,动态分配内存和一些对输入输出流的基本操作。
Matrix类:
#ifndef MATRIX_H
#define MATRIX_H
#include <iostream>
#include <fstream>
#include <string>
using std::istream;
using std::ostream;
using std::string;
using std::ifstream;
using std::ofstream;
class Matrix
{
//对经常使用的运算符的重载
friend ostream& operator<<(ostream& osm, const Matrix& mat);
friend istream& operator >> (istream& ism, Matrix& mat);
friend Matrix operator+(const Matrix& l, const Matrix& r);
friend Matrix operator-(const Matrix& l, const Matrix& r);
friend Matrix operator*(const Matrix& l, const Matrix& r);
public:
//构造函数和析构函数
Matrix() :m_nRow(0), m_nCol(0), m_pData(nullptr) {}
Matrix(int nRow, int nCol, double* pData = nullptr);
Matrix(const string& strMatrixFile); //Creat a Matrix form a file
Matrix(const Matrix&src);
virtual ~Matrix();
//类基本都有的东西
long Size()const { return m_nRow*m_nCol; }
int GetRows()const { return m_nRow; }
int GetCols()const { return m_nCol; }
bool Empty()const { return Size() == 0; }
const Matrix& operator=(const Matrix& r);
protected:
void Load(istream& ism); //从键盘等中读取数据
void save(ostream& osm)const; //存储矩阵数据到文件中
void Copy(void* Sourse, int nRow, int nCol); //实现矩阵的拷贝
bool judge(const Matrix& l, const Matrix& r); //判断能否相加或相减
private:
int m_nRow; //行数
int m_nCol; //列数
double* m_pData; //储存数据
};
#endif // !MATIRX_H
具体实现的代码:
#include "Matrix.h"
#include <iostream>
#include <cassert>
#include <fstream>
#include <string>
#include <iomanip>
//安全删除指针
#define SAFE_DELETE(p) {if(p) {delete[]p;p=nullptr;}}
using namespace std;
//注意不能浅拷贝
void Matrix::Copy(void* Sourse, int nRow, int nCol) {
if (nRow*nCol){
m_nRow = nRow;
m_nCol = nCol;
if (Size()){
m_pData = new double[Size()];
if (m_pData) {
size_t size = Size() * sizeof(double);
memset(m_pData, 0, size);
if (Sourse)
memcpy_s(m_pData, size, Sourse, size);
}
}
}
else
cerr << "Please use another matrix!" << endl;
}
//析构函数
Matrix::~Matrix(){
SAFE_DELETE(m_pData);
}
Matrix::Matrix(int nRow, int nCol, double* pData){
assert(pData&&nRow&&nCol); //对错误操作进行警告
Copy(pData, nRow, nCol);
}
Matrix::Matrix(const string& strMatrixFile){
ifstream infile(strMatrixFile);
string tmp;
if (!infile){
cerr << "Can not open the file!" << endl;
return;
}
// 读取列数
char c = infile.peek();
while (('\n' != c) && infile){
infile >> tmp;
++m_nCol;
c = infile.peek();
}
// 读取行数
infile.clear();
infile.seekg(0, ios::beg);
while (getline(infile, tmp, '\n'))
if (tmp.size() > 0)
++m_nRow;
// 读取数字
infile.clear();
infile.seekg(0, ios::beg);
m_pData = new double[Size() + 1];
double *temp = m_pData;
while (infile.peek() != EOF)
infile >> *m_pData++;
m_pData = temp;
infile.close();
}
//拷贝构造函数
Matrix::Matrix(const Matrix&src){
assert(src.m_pData&&src.m_nRow&&src.m_nCol);
Copy(src.m_pData, src.m_nRow, src.m_nCol);
}
const Matrix& Matrix::operator=(const Matrix& r){
if (this != &r){
Copy(r.m_pData, r.m_nRow, r.m_nCol);
return *this;
}
}
void Matrix::Load(istream& ism){
ism >> m_nRow >> m_nCol;
if (m_nRow > 0 && m_nCol > 0) {
SAFE_DELETE(m_pData);
m_pData = new double[Size()];
if (m_pData != nullptr) {
for (size_t i = 0; i < Size(); ++i)
ism >> m_pData[i];
}
}
}
void Matrix::save(ostream& osm)const{
//osm << m_nRow << " " << m_nCol << endl;
if (m_nRow > 0 && m_nCol > 0) {
for (size_t i = 0; i < Size(); ++i){
osm << setw(12) << setiosflags(ios::right)<< m_pData[i] << " ";
if ((i + 1) % m_nCol == 0)
osm << endl;
}
}
}
ostream& operator<<(ostream& osm, const Matrix& mat){
if (mat.Empty()){
osm << "No numbers" << endl;
return osm;
}
mat.save(osm);
return osm;
}
istream& operator >> (istream& ism, Matrix& mat){
mat.Load(ism);
return ism;
}
bool Matrix::judge(const Matrix& l, const Matrix& r) {
assert(l.m_nRow == r.m_nRow && l.m_nCol == r.m_nCol);
if (l.m_nRow != r.m_nRow || l.m_nCol != r.m_nCol){
cout << "Can not caculate these two matrixs!" << endl;
return false;
}
if (l.Empty()){
cout << "No number!" << endl;
return false;
}
this->m_nRow = l.m_nRow;
this->m_nCol = l.m_nCol;
this->m_pData = new double[l.Size()];
return true;
}
Matrix operator+(const Matrix& l, const Matrix& r){
//ofstream osm("Matrix3.txt");
Matrix temp;
if (!temp.judge(l, r))
return temp;
for (size_t i = 0; i < temp.Size(); ++i) {
temp.m_pData[i] = r.m_pData[i] + l.m_pData[i];
}
//temp.save(osm);
//osm.close();
return temp;
}
Matrix operator-(const Matrix& l, const Matrix& r){
//ofstream osm("Matrix3.txt");
Matrix temp;
if (!temp.judge(l, r))
return temp;
for (size_t i = 0; i < temp.Size(); ++i) {
temp.m_pData[i] = l.m_pData[i] - r.m_pData[i];
}
//temp.save(osm);
//osm.close();
return temp;
}
Matrix operator*(const Matrix& l, const Matrix& r){
//ofstream osm("Matrix3.txt");
Matrix temp;
bool bCanOp = l.m_nCol == r.m_nRow;
assert(bCanOp);
if (l.m_nCol != r.m_nRow){
cout << "Can not caculate these two matrixs!" << endl;
return temp;
}
if (l.Empty()){
cout << "No number!" << endl;
return temp;
}
temp.m_nRow = l.m_nRow;
temp.m_nCol = r.m_nCol;
temp.m_pData = new double[temp.Size() + 1];
//实现矩阵的乘法
if (temp.m_pData){
for (size_t i = 0; i < l.m_nRow; ++i){
for (size_t j = 0; j < r.m_nCol; ++j){
double sum = 0;
for (size_t k = 0; k < r.m_nRow; ++k) {
sum += l.m_pData[i*l.m_nCol + k] * r.m_pData[k*r.m_nCol + j]; //这是用一维数组表示二维数组的方法
}
temp.m_pData[r.m_nCol*i + j] = sum;
}
}
//temp.save(osm); 如果需要存到文件中加上此代码
//osm.close();
return temp;
}
}
一些心得:
注意深拷贝和浅拷贝的区别, 在需要动态分配内存的时候不能浅拷贝, 因为析构函数会释放掉被拷贝数据的存在的空间。还有就是在删除指针时一定要先判断。