矩阵模板类

测了下int型没问题,之后再完善,还有个卷积运算没看懂懒得做,其他应该都做好了,做的比较快,比较粗糙,也没人测,但大致功能应该都行。

#pragma once
#include <iostream>
#include <string>
#include <vector>
#include "..\utils\FileOperation.h"
#include "..\utils\Utils.h"
#include <sstream>
using namespace std;


#define  MinSize 1                             //控制行列最小值
#define  MaxSize 500                           //控制行列最大值


template <class T>
class CMat;

template<class T>
class CMat
{

	template <class U>
	friend CMat<U> operator*(CMat<U>&,CMat<U>&); //矩阵乘法

public:

//---------------构造
	CMat<T>() = delete;                         //删除默认构造函数
	CMat<T>(int r, int c, T value);             //指定行数r、列数c构造初始值均为value的矩阵
	CMat<T>(int r, int c, T* arr);              //给定一维数组arr,构建r行、c列矩阵
	CMat<T>(int r, int c);                      //创建构建r行、c列矩阵,矩阵值从键盘中输入

//---------------析构
	virtual ~CMat();                            //析构函数

//---------------拷贝构造(deep copy)
	CMat<T>(CMat<T>&);


//---------------方法
	void printMat() const;                      //按矩阵行列格式打印矩阵
	void saveMat(const char *filename);         //保存矩阵数据到文件
	void loadMat(const char *filename);         //从文件中读取数据到矩阵
	int  getRows() const;                       //读取矩阵的行数
	int  getCols() const;                       //读取矩阵的列数
	bool isSquare() const;                      //判断是否为方阵
	void reSize(int p, int q);                  //将矩阵形状变换为p行、q列

	CMat<T> fetchRow(int row);                  //取给定行所有元素 row col从0开始取
	CMat<T> fetchCol(int col);                  //取给定列所有元素 row col从0开始取
	void swapRows(int a, int b);                //交换矩阵第a行和第b行元素的值 row col从0开始取
	void swapCols(int a, int b);                //交换矩阵第a列和第b列元素的值row col从0开始取
	static CMat<T> createEyeMat(int n);         //创建一个行数列数均为n的单位矩阵


	void detMat();                             //求矩阵行列式
	CMat<T>convMat(CMat<T>a, CMat<T>b);        //矩阵卷积运算

//---------------重载						    
	T operator()(int row, int col);            //按给定的行和列取元素 row col从0开始取
	CMat<T>&operator+(CMat<T>&);               //矩阵加法
	CMat<T>&operator-(CMat<T>&);               //矩阵减法
	CMat<T>&operator=(CMat<T>&);               //矩阵深度复制
	bool operator==(CMat<T>&);                 //判断矩阵相等
	bool operator!=(CMat<T>&);                 //判断矩阵不相等

private:
	int row;                                   //行
	int col;                                   //列
	T*  data;                                  //指向数据的一维指针
};


template<class T>
void CMat<T>::printMat() const
{
		cout<<"当前实例矩阵为:\n";
	cout << "-------------------\n";
	for(int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			cout<<*(data + i*col + j);
			if (j < col - 1)
			{
				cout << "    ";
			}
			else if(j==col-1)
			{
				cout <<"\n";
			}
		}
	}
	cout << "-------------------\n";
}

template<class T>
void CMat<T>::saveMat(const char *filename)
{
	//文件格式: 1   21  21
	//          12  23  32     
	//          12  23  11 
	//          23  12  33

	string write_str = "";

	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			//string cur_str=atio

			if (write_str == "")
			{
				write_str += to_string(*(data + i*col + j));
			}
			else
			{

				if (j == col - 1)
				{	//每行的最后一个加换行符
					write_str += " ";
					write_str += to_string(*(data + i*col + j));
					write_str += "\n";
				}
				else if (j == 0)
				{
					//每行的第一个什么都不加
					write_str += to_string(*(data + i*col + j));
				}
				else
				{
					//中间段 加空格即可
					write_str += " ";
					write_str += to_string(*(data + i*col + j));
				}
			}
		}
	}

	//删除结尾的\n
	write_str.pop_back();


	//暂时不考虑中文编码问题-有需求再加
	//if (!FileOperation::IsFileExist(filename))/不考虑不存在
	//{
	//	return;
	//}

	//删除旧的
	bool delete_ret = FileOperation::GetFileOperation()->DeleteFile(filename);

	//如果没有 创建一个 然后直接写入
	bool create_ret = FileOperation::GetFileOperation()->CreateFile(write_str, filename);
	//失败情况不考虑
}

template<class T>
void CMat<T>::loadMat(const char *filename)
{
		//cout<<"开始读取"<< endl;
		string read_str;
		if (!FileOperation::GetFileOperation()->IsFileExist(filename)) //不考虑不存在
		{
			cout << "读取的文件路径不存在:" << filename << endl;
			return;
		}
		else
		{
			bool read_ret = FileOperation::GetFileOperation()->ReadStringFromFile(filename, read_str);
		}

		//将字符串分割获取每一行
		vector<string>all_row_vec;
		SplitString(read_str, all_row_vec, "\n");

		if (all_row_vec.size() <= 0)
		{
			cout << "读取文件失败" << filename << endl;
		}

		this->row = static_cast<int>(all_row_vec.size());
		cout << "文件矩阵行数" << to_string(row) << endl;


		//先取第一行列数 来构造data
		vector<string>first_row_vec;
		SplitString(all_row_vec[0], first_row_vec, " ");
		if (first_row_vec.size() <= 0)
		{
			cout << "读取文件失败" << filename << endl;
			return;
		}
		//去第一行分割的列数 赋值给当前类
		this->col = static_cast<int>(first_row_vec.size());
		cout << "文件矩阵列数" << to_string(col) << endl;

		//构造data
		data = new T[col*row];


		//以下语句赋值有崩溃风险 必须保证文件存取一定要正确
		for (int i = 0; i < all_row_vec.size(); i++)
		{
			vector<string>one_row_vec;
			SplitString(all_row_vec[i], one_row_vec, " ");

			for (int j = 0; j < col; j++)
			{
				istringstream iss(one_row_vec[j]);
				T num;
				iss >> num;
				*(data + i*col + j) = num;
			}
		}
		//cout << "结束读取,读取成功" << endl;
}

template<class T>
int CMat<T>::getRows() const
{
	cout << "当前矩阵行数 " << to_string(row) << endl;
	return row;
}

template<class T>
int CMat<T>::getCols() const
{
	cout << "当前矩阵列数 " << to_string(col) << endl;
	return col;
}

template<class T>
bool CMat<T>::isSquare() const
{
	if (col == row)
	{
		cout << "当前矩阵是方阵" << endl;
		return true;
	}
	else
	{
		cout << "当前矩阵不是方阵" << endl;
		return false;
	}
}

template<class T>
void CMat<T>::reSize(int p, int q)
{
	//p*q必须和当前矩阵row*col一样
	if (p*q != row*col)
	{
		//不符合条件取消
		return;
	}

	//符合条件,进行变换
	//直接将row和col用p q赋值即可
	this->row = p;
	this->col = q;
}

template<class T>
T CMat<T>::operator()(int row, int col)
{
	if (row < 0 || row >= this->row || col < 0 || col >= this->col)
	{
		cout << "重载()输入超出范围" << endl;
	}
	T cur_value = *(data + row*(this->col) + col);
	cout << "该矩阵第" << to_string(row) << "行,第" << to_string(col) << "列值为:" << to_string(cur_value) << endl;
	return cur_value;
}

template<class T>
CMat<T>& CMat<T>::operator+(CMat<T>&mat)
{
		//判断是不是同型的矩阵
		int target_row = mat.getRows();
		int target_col = mat.getCols();

		if (target_row != this->row || target_row != this->col)
		{
			cout << "不同型矩阵不能相加" << endl;
		}

		//数据部分不判断了

		T*target_data = mat.data;

		//相加
		for (int i = 0; i < row; i++)
		{
			for (int j = 0; j < col; j++)
			{
				T target_value = *(target_data + i*row + j);
				T cur_value = *(this->data + i*row + j);
				*(this->data + i*row + j) = cur_value + target_value;
			}
		}
		return *this;
}

template<class T>
CMat<T>& CMat<T>::operator-(CMat<T>&mat)
{	//判断是不是同型的矩阵
	int target_row = mat.getRows();
	int target_col = mat.getCols();

	if (target_row != this->row || target_row != this->col)
	{
		cout <<"不同型矩阵不能相减"<<endl;
	}

	//数据部分不判断了
	T*target_data = mat.data;

	//相加
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			T target_value = *(target_data + i*row + j);
			T cur_value = *(this->data + i*row + j);
			*(this->data + i*row + j) = cur_value - target_value;
		}
	}
	return *this;
}

template<class T>
CMat<T> CMat<T>::convMat(CMat<T>a, CMat<T>b)
{

}

template<class T>
void CMat<T>::detMat()
{

}

template<class T>
CMat<T> CMat<T>::createEyeMat(int n)
{
	T*data = new T[n*n];
	for (int i = 0; i < n*n; i++)
	{
		*(data + i) = 1;
	}

	static CMat<T>result_mat(n, n, data);

	return result_mat;
}

template<class T>
void CMat<T>::swapCols(int a, int b)
{
	//判断
	if(a <0||a>= col||b<0||b>=col)
	{
		//参数不符合条件
		return;
	}

	//new一个暂存的数据 存下b列的数据 有row项
	T*temp_data = new T[row];
	for(int i= 0;i<row;i++)
	{
		//将b列数据给到temp_data,b列数据用a列数据赋值,a列数据用temp_data赋值
		*(temp_data + i) = *(data + i*col+b);
		*(data + i*col +b) = *(data + i*col +a);
		*(data + i*col + a) = *(temp_data +i);
	}
	delete[]temp_data;
	return;
}

template<class T>
void CMat<T>::swapRows(int a, int b)
{
	//判断
	if(a<0||a>=row||b<0||b>= row)
	{
		//参数不符合条件
		return;
	}

	//new一个暂存的数据 存下b行的数据 有col项
	T*temp_data = new T[col];

	for(int j=0; j<col; j++)
	{
		//将b行数据给到temp_data,b行数据用a行数据赋值,a行数据用temp_data赋值
		*(temp_data + j) = *(data + b*col + j);
		*(data + b*col + j) = *(data + a*col + j);
		*(data + a*col + j) = *(temp_data + j);
	}

	delete[]temp_data;
	return;
}

template<class T>
CMat<T> CMat<T>::fetchCol(int col)
{
	//给定行,则矩阵为n行 1列  参数col从0开始取
	int mat_row = this->row;
	int mat_col = 1;

	T*data = new T[mat_row*mat_col];

	for (int i= 0; i< mat_row; i++)
	{
		*(data + i) = *(this->data + row*i + col);
	}
	CMat<T>result_mat(mat_row, mat_col, data);
	return result_mat;
}

template<class T>
CMat<T> CMat<T>::fetchRow(int row)
{
	//给定行,则矩阵为1行 n列  参数row从0开始取
	int mat_row =1;
	int mat_col= this->col;

	T*data = new T[mat_row*mat_col];


	for (int j = 0; j < mat_col; j++)
	{
		*(data + j) = *(this->data + row*col + j);
	}
	CMat<T>result_mat(mat_row, mat_col,data);
	return result_mat;
}

template<class T>
bool CMat<T>::operator!=(CMat&)
{
	//判断是不是同一个对象
	if (this == &mat)
	{
		return false;
	}

	//判断数据是否相等
	T *target_data = mat.data;
	bool is_data_equal = true;
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			T target_value = *(target_data + i*row + j);
			T cur_value = *(this->data + i*row + j);
			if (target_value != cur_value)
			{
				is_data_equal = false;
			}
		}
	}
	if (mat.row==this->row&&mat.col==this->col&&is_data_equal)
	{
		return false;
	}
	return true;
}

template<class T>
bool CMat<T>::operator==(CMat&mat)
{
	//判断是不是同一个对象
	if (this == &mat)
	{
		return true;
	}

	//判断数据是否相等
	T *target_data = mat.data;
	bool is_data_equal=true;
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			T target_value = *(target_data + i*row + j);
			T cur_value = *(this->data + i*row + j);
			if (target_value != cur_value)
			{
				is_data_equal = false;
			}
		}
	}


	if (mat.row != this->row || mat.col != this->col || !is_data_equal)
	{
		return false;
	}
	return true;
}

template<class T>
CMat<T>& CMat<T>::operator=(CMat&mat)
{
	//判断是不是同一个对象
	if (this== &mat)
	{		
		return *this;
	}

	if (this->data != NULL)
	{
		delete [] this->data;
	}
	this->row = mat.row;
	this->col = mat.col;
	this->data = new T(row*col);
	//深拷贝
	memcpy(this->data, mat.data,row*col * sizeof(T)); //后面sizeof(T)不要忘记
	return *this;
}


template<class U>
CMat<U> operator*(CMat<U>&mat1, CMat<U>&mat2)
{
	U*temp_data = new U[1];
	*temp_data = 1;
	CMat<U>result_mat(1, 1, temp_data);

	//第一个矩阵的列数col和第二个矩阵的行数row相同才可相乘
	//判断是不是同一个对象
	if (mat1 == mat2)
	{
		return  result_mat;
	}
	if (mat1.col != mat2.row || mat1.row < 0 || mat1.col < 0 || mat2.row < 0 || mat2.col < 0)
	{
		//不符合要求
		return result_mat;
	}

	//通过判断 开始矩阵相乘
	int result_row = mat1.row;
	int result_col = mat2.col;



	//清除之前的内存空间,重新分配空间 !!这里不需要清除空间 析构会调用 会删除一次报错
	//delete[]temp_data;
	//temp_data = NULL;
	
	U *new_data = new U[result_row*result_col];
	
   
	//a第i行和b第j列相乘,相加
	int num = mat1.col;//取一个基准数值 应等于a列 或者b行
	for (int i = 0; i < result_row; i++)
	{
		for (int j = 0; j < result_col; j++)
		{
			//从mat1的第i行取num列数的值  从mat2的第j列取num行数的值 相乘再相加  
			U result_value = 0;
			for (int k = 0; k < num; k++)
			{
				U value = (*(mat1.data + i*mat1.col + k))*(*(mat2.data + j + k*mat2.col));
				result_value += value;
			}
			*(new_data + i*result_col + j) = result_value;
		}
	}
	CMat<U>new_mat(result_row, result_col, new_data);
	return new_mat;
}

template<class T>
CMat<T>::CMat(CMat&mat)
{
	if (mat.row<MinSize || mat.row>MaxSize || mat.col<MinSize || mat.col>MaxSize|| mat.data==NULL)
	{
		//不符合要求
		assert(0);
		return;
	}

	this->row = mat.row;
	this->col = mat.col;

	//申请空间
	data = new T[row*col];
	//深拷贝
	memcpy(this->data, mat.data, row*col*sizeof(T));
}

template<class T>
CMat<T>::CMat(int r, int c, T value)
{
	if (r<MinSize || r>MaxSize || c<MinSize || c>MaxSize)
	{
		//行列不符合要求
		assert(0);
		return;
	}
	//构造
	data = new T[r*c];

	//赋值
	for (int cur_r = 0; cur_r < r; r++)
	{
		for (int cur_c = 0; cur_c < c; c++)
		{
			*(data + cur_r*cur_c - 1) = value;
		}
	}
}

template<class T>
CMat<T>::CMat(int r, int c, T* arr)
{
	if (r<MinSize || r>MaxSize || c<MinSize || c>MaxSize || arr == NULL)
	{
		assert(0);
		return;
	}
	//这里要再加个判断 判断 arr是否符合r*c的size

	this->row = r;
	this->col = c;
	this->data = arr;

}

template<class T>
CMat<T>::CMat(int r, int c)
{
	if (r<MinSize || r>MaxSize || c<MinSize || c>MaxSize)
	{
		//行列不符合要求或者数据指向为空
		cout << "Struct failed---OutOfRange" << endl;
		return;
	}

	//开始
	this->data = new T[r*c];
	this->row = r;
	this->col = c;

	int size = r*c;
	cout << "需要输入:" << to_string(size) << "个数字" << "\n";

	for (int i = 0; i < size; i++)
	{
		cout << "编号:" << to_string(i) << " " << "数值:";
		T input;
		cin >>input;
		//赋值
		*(data + i) = input;
	}
}

template <class T>
CMat<T>::~CMat()
{
	if (this->data != NULL)
	{
		delete[]data;
	}
}


猜你喜欢

转载自blog.csdn.net/qq_36533978/article/details/106936526
今日推荐