如何写一个头文件?

· · 个人记录

255最近刚学了矩阵,因为矩阵实在是太难了,所以他照着老师课件上的计算方法一气之下写了个简陋的头文件,这样他就不用背那些复杂的知识点了

你将在本文看到的:

  1. 写一个头文件的思路
  2. 一个简陋的matrix.h头文件

如何开始?

如果想写一样东西,那么你就要构思这个东西是什么样的。比如说:

  1. 这个头文件都需要有什么功能?
  2. 怎么写这些功能?
  3. 如何写成一个模板?
  4. 如何使用写好的头文件?

这个头文件都需要什么功能?

为了想这一点,我先简单的写了一段代码:

#include <matrix.h>
using namespace std;
int main(){
    Matrix<int> a, b;
    a.read(); b.read();
    a.print();
    cout << endl;
    b.print();
    cout << endl;

    Matrix<int> c,d,e;
    c.matrix = a.matrix * b.matrix;
    d.matrix = a.matrix + b.matrix;
    e.matrix = a.matrix - b.matrix;
    //为什么没有除呢?其实很简单,因为我不会(
    c.print(); d.print(); e.print();
    cout << endl;

    c.transpose();
    c.print();
    return 0;
}

之后我们就可以一目了然的看出我们需要的功能了。

怎么写这些功能?

开始敲大致结构

首先,我们应该新建一个类,这样可以既可以使我们的思路保持清晰,而且类还有继承,封装,多态性,对象化等特性。对于一个类,大致长得像下面这样:

class ......{
    public: ......
    private: ......
    protected: ......
}

所以,我们应该在public内开数组及函数,大致写一下可得:

#include <bits/stdc++.h>
using namespace std;
class Matrix{
    public:
        vector< vector<int> > matrix;
        void read(){
            cin >> ln >> col;
            for(register int i = 0; i < col; i++){
                for(register int j = 0; j < ln; j++){
                    cin >> tmp;
                    swp.push_back(tmp);
                }
                matrix.push_back(swp);
                swp.clear();
            }
        }
        void print(){
            for(register int i = 0; i < col; i++){
                for(register int j = 0; j < ln; j++){
                    cout << matrix[i][j] << ' ';
                }
                cout << endl;
            }
        }
    private:
        int col=0, ln=0;
        int tmp=0;
        vector<int> swp;
}

再然后要写的,就只有一些函数和运算符重载了,函数具体可以访问这里

那么,如何重载运算符呢?

重载运算符

我们都知道,一个矩阵在代码里本质上就是一个二维数组,所以我们要重载的运算符类型也就很显然了。那么我们重载一个加法看看:

\begin{bmatrix} a_1 & a_2 & a_3\\ a_4 & a_5 & a_6\\ a_7 & a_8 & a_9\\ \end{bmatrix} + \begin{bmatrix} b_1 & b_2 & b_3\\ b_4 & b_5 & b_6\\ b_7 & b_8 & b_9\\ \end{bmatrix} = \begin{bmatrix} a_1+b_1 & a_2+b_2 & a_3+b_3\\ a_4+b_4 & a_5+b_5 & a_6+b_6\\ a_7+b_7 & a_8+b_8 & a_9+b_9\\ \end{bmatrix}

(矩阵加法运算过程)

vector< vector<int> > operator + (const vector< vector<int> > &a, const vector< vector<int> > &b){
    vector< vector<int> > c;
    if(a.size()==0||b.size()==0){ //特判0*0矩阵的情况,否则可能会出错
        return c; //返回空矩阵
    }
    int lnA = a.size();  //A矩阵 - 行数
    int colA = a[0].size();   //A矩阵 - 列数
    int lnB = b.size();  //B矩阵 - 行数
    int colB = b[0].size(); //B矩阵 - 列数 
    if (colA != colB||lnA != lnB){ //非两个m*n矩阵无法相加
        return c; //返回空矩阵
    }
    c.resize(lnA); //调节行数 
    for (int i = 0; i < lnA; ++i)  {  
        c[i].resize(lnB);  //调节列数
    }
    for(register int i = 0; i < lnA; i++){
        for(register int j = 0; j < lnA; j++){
            c[i][j] = a[i][j] + b[i][j]; //相加
        }
    }
    return c;
}

同理,我们也可以类比出减法的表示方式,只需要把+改为-即可

那么如何乘呢?

课件是这么说的:Am \times p的矩阵,Bp \times n的矩阵,那么称m \times n的矩阵C为矩阵AB的乘积,记作C = AB,其中矩阵C中的第i行第j列元素可以表示为:

(AB)_{ij} = \sum_{k=1}^pa_{ik}b_{kj}

所以可以写出代码如下:

vector< vector<int> > operator * (const vector< vector<int> > &a, const vector< vector<int> > &b){
    vector< vector<int> > c;
    if(a.size()==0||b.size()==0){//特判0*0矩阵
        return c;
    }
    int lnA = a.size();  
    int colA = a[0].size();  
    int lnB = b.size();  
    int colB = b[0].size();  
    if (colA != lnB){//特判是否m*p p*n
        return c;
    }
    c.resize(lnA);  
    for (int i = 0; i < lnA; ++i)  {  
        c[i].resize(colB);  
    }
    for (int i = 0; i < lnA; ++i){  
        for (int j = 0; j < colB; ++j){  
            for (int k = 0; k < colA; ++k){  
                c[i][j] += a[i][k] * b[k][j];//公式
            }  
        }  
    }  
    return c;
}

到这里,我们已经写完了全部的功能!完结撒花(

如何写成一个模板?

我们的代码里好像有过这样的一段:

Matrix<int> a, b;

那么,尖括号可以由我们自己觉得是什么类型的matrix又是怎么做到的呢?

这时,就要用到我们的模板(template)大法了。

template <typename _(1)_ > _(2)_;

其中,(1)处要跟一个我们给这个任意的变量类型所起的名字,一般叫做T。(2)处要跟我们的函数

而这里,我们只需要在我们的Matrix类前加上template,如下:

template<typename T> class Matrix{ ....... };

然后,再把所有变量类型改为T即可(ln,col)除外。如:

vector< vector<T> > matrix;
......

这把就真的完结撒花了!文件请看这里

如何使用?

首先,将文件保存为.h(推荐)格式或其他,然后放入你的编译器include目录下。在我的电脑里,编译器include在这里:

C:\Program Files (x86)\Dev-Cpp\MinGW64\lib\gcc\x86_64-w64-mingw32\4.9.2\include

然后

#include <你的文件名.你保存的格式> 

即可

测试程序