矩阵类

矩阵类

今天c程序设计课的内容是要求我们封装矩阵的一些运算,然后突然想到前段时间做过关于大整数类的问题,就想着能不能依葫芦画瓢的做一个矩阵类。

尝试了大半个晚上,感觉还是可行的,重载了输入输出赋值和一些简单的矩阵运算(细节没有处理的很好,使用的时候可能会出现一些小bug),至于矩阵的逆运算,特征值还有秩感觉比较复杂,所以暂时还没有深入地去做。


和大整数类一样,我们一段一段的进行编译:

首先是构造函数,和矩阵的一些特征:

//行和列,data表示用于存放每个单位值的数组 
	int row,col,data[100][100]; 
	//构造函数 
	Square(){
     }
	Square(const Square&x) {
     *this=x;}
    Square(const string&x) {
     *this=x;}

接下来是重载赋值运算符。由于课上的实验你可以自拟矩阵的行和列,但更多时候是直接给你一个未知行和列长度的矩阵,那我们怎么得到矩阵的行和列呢?

我们在split那一章的时候,学习了getline的运用,于是这里用getline的第二个用法:将整个矩阵视作一个字符串,q为这个字符串的结束,然后以回车符为分割符得到每一行的字符串,再对每一行字符串用空格作分割符得到每一个字符串,再将字符串转化为一个一个的数字。

代码如下:

Square &operator=(const string &x){
     
    	int row1=0,col1=0;
    	//这是上次提到的切割字符串的方法 
    	string p; stringstream streamR(x); 
    	while (getline(streamR,p)){
     //先按照回车切割 
			row1++;col1=0;
			stringstream streamQ(p);string s;
			while (getline(streamQ,s,' ')){
     //再按照空格切割得到的即是一个一个数字 
				col1++;data[row1][col1]=0;
				int sign=(s[0]=='-');//字符串转化为数字,判断第一位是否为0 
				for (int i=s.size()-1,j=1;i>=0+sign;i--,j*=10) data[row1][col1]+=j*((int)s[i]-48);
				data[row1][col1]*=sign?-1:1; 
			}
		}
		row=row1; col=col1;
		return *this;
	}

(我可以用ssprintf转化字符串,我就是不用。哎,就是玩儿!)

接下来是重载输入和输出的运算符,需要注意的是,重载输入运算符时,需要用getline处理istream:

//重载输入符 
	friend istream &operator>>(istream &in,Square &x){
     
		string str; getline(in,str,'q');
		x=str.c_str(); return in;
	}
	//重载输出运算符
	friend ostream &operator<<(ostream &out,Square &x){
     
		for (int i=1;i<=x.row;i++){
     
			for (int j=1;j<=x.col;j++){
     out<<x.data[i][j]<<" ";}
			out<<endl;
		}
		return out;
	}

(这里的输出其实是有一些问题的,应该要转化为字符串的)

做到这里,我们已经可以做简单的输入和输出了:

矩阵类_第1张图片

接下来就该做运算符了,首先是加法:

//+运算符,只有行数列数相同的矩阵才可以相加,不然会显示出错了 
	Square operator+(const Square &b) const{
     
		if (b.row==row&&b.col==col){
     
			Square C;C.row=row;C.col=col;
			for (int i=1;i<=C.row;i++)
				for (int j=1;j<=C.col;j++) C.data[i][j]=b.data[i][j]+data[i][j];
			return C;
		}
		else cout<<"出错了";
	

如果你认真的阅读过大整数类的那里的代码,领略过那里的思想,我相信矩阵的加法对你是非常简单的(我相信你没有)。

减法:

//-运算符
	Square operator-(const Square &b) const{
     
		if (b.row==row&&b.col==col){
     
			Square C;C.row=row;C.col=col;
			for (int i=1;i<=C.row;i++)
				for (int j=1;j<=C.col;j++) C.data[i][j]=-b.data[i][j]+data[i][j];
			return C;
		}
		else cout<<"出错了";
	}

乘法相对而言会特殊一点,不过也不会特殊的太多,只需要遵循线性代数的计算法则即可:

	//*运算符,需要注意的是可以相乘的两个矩阵,左行需要等于右列
	//得到的矩阵的行数等于右边矩阵的行数,列数为左边矩阵的列数 
	Square operator*(const Square &b) const{
     
		if (b.row==col){
     
			Square C;C.row=row;C.col=b.col;
			for (int i=1;i<=C.row;i++){
     
				for (int j=1;j<=C.col;j++){
     
					C.data[i][j]=0;
					for (int k=1;k<=col;k++) C.data[i][j]+=data[i][k]*b.data[k][j];
				}
			}
			return C;
		}
		else cout<<"出错了";
	}

还有一个转置函数:

//转置
	Square rev()const{
     
		Square C;C.row=col;C.col=row;
		for (int i=1;i<=C.row;i++)
			for (int j=1;j<=C.col;j++) C.data[i][j]=data[j][i];
		return C;
	} 

以上的代码都是可以拿来直接使用的,不过比较可惜的是,一方面是因为时间比较仓促,另一方面是我对于c++类的操作并不熟练,导致上面的代码可能会有一些用的不顺畅的地方(基本是输出的时候,我输出那里偷懒了)或者小bug:
矩阵类_第2张图片
比如说这里,由于我的getline是以q为终止符的,导致输入q换行的时候,换行符会被计入下一个矩阵中,导致出错,那我是怎么处理的呢?

矩阵类_第3张图片
(这是线代书上的一道例题哦)

所以最后的最后,还是希望大家能够指出我代码的bug。如果知道上面的代码有什么加快运算的方法,或者对处理矩阵的逆运算,秩,特征值有想法的,欢迎大家一起交流学习啊。(我是five)

你可能感兴趣的:(问题解决,程序设计,算法,c++)