C++ 实现矩阵类

这是矩阵类的一个简单实现,里面主要运用了运算符重载,动态分配内存和一些对输入输出流的基本操作。

Matrix类:

#ifndef MATRIX_H
#define MATRIX_H

#include 
#include 
#include 

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 
#include 
#include 
#include 
#include 
//安全删除指针
#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;
	}
}



一些心得:
注意深拷贝和浅拷贝的区别, 在需要动态分配内存的时候不能浅拷贝, 因为析构函数会释放掉被拷贝数据的存在的空间。还有就是在删除指针时一定要先判断。

你可能感兴趣的:(C++)