数组传参很常见,在 C/C++ 中传递数组时,数组名会退化为指针,所以一般都要给出首地址和长度。这是有缺陷的,当我们在写函数时不知道各维大小时该怎么办呢?
下面用矩阵乘法作为例子,给出三种实现方法:GP, flattening the array, struct
其中我认为 flattening the array 这种方法最好,OpenGL 中的 glMaplf 函数用的正是这种方法,它的函数原型如下:
void glMap1f(GLenum target, GLfloat uMin, GLfloat uMax, GLint stride, GLint order, const GLfloat *controlPointsPtr);
参数介绍如下
一、源程序
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
const int MAX_ROW = 10;
const int MAX_COLUMN = 10;
template <class T>
struct Matrix {
unsigned int row;
unsigned int column;
T m[MAX_ROW][MAX_COLUMN];
Matrix(unsigned int _row, unsigned int _column):row(_row), column(_column) {
memset(m, 0, sizeof(m));
}
};
// GP
template<unsigned int x, unsigned int y, unsigned int z, class T>
void GPMatrixMultiply(T A[x][y], T B[y][z], T C[x][z])
{
for (int i = 0; i < x; ++i) // 有符号数与无符号数的比较,没有给出警告 Why?
{
for (int j = 0; j < z; ++j)
{
C[i][j] = 0;
for (int k = 0; k < y; ++k)
{
C[i][j] += A[i][k] * B[k][j];
}
}
}
}
// flattening the array
template<class T>
void FlattenMatrixMultiply(T *p, T *q, T *r, unsigned int x, unsigned int y, unsigned int z)
{
for (unsigned int i = 0; i < x; ++i)
{
for (unsigned int j = 0; j < z; ++j)
{
r[i * z + j] = 0;
for (unsigned int k = 0; k < y; ++k)
{
r[i * z + j] += p[i * y + k] * q[k * z + j];
}
}
}
}
// struct
template <class T>
Matrix<T> StructMatrixMultiply(Matrix<T> A, Matrix<T> B)
{
Matrix<T> C(A.row, B.column);
for (unsigned int i = 0; i < A.row; ++i)
{
for (unsigned int j = 0; j < B.column; ++j)
{
C.m[i][j] = 0;
for (unsigned int k = 0; k < A.column; ++k) // 待检测A.column == B.row
{
C.m[i][j] += A.m[i][k] * B.m[k][j];
}
}
}
return C;
}
#pragma region 定义的输入输出函数
template<class T>
istream & operator>>(istream& is, const Matrix<T> &matrix)
{
for (unsigned int i = 0; i < matrix.row; ++i)
{
for (unsigned int j = 0; j < matrix.column; ++j)
{
is >> T(matrix.m[i][j]);
}
}
return is;
}
template<class T>
ostream & operator<<(ostream& os, const Matrix<T> &matrix)
{
for (unsigned int i = 0; i < matrix.row; ++i)
{
for (unsigned int j = 0; j < matrix.column; ++j)
{
os << matrix.m[i][j] << " ";
}
os << endl;
}
return os;
}
template<unsigned int row, unsigned int column, class T>
void InputMatrix(T matrix[row][column])
{
for (int i = 0; i < row; ++i)
{
for (int j = 0; j < column; ++j)
{
cin >> matrix[i][j];
}
}
}
template<unsigned int row, unsigned int column, class T>
void OutputMatrix(T matrix[row][column])
{
for (int i = 0; i < row; ++i)
{
for (int j = 0; j < column; ++j)
{
cout << matrix[i][j] << " ";
}
cout << endl;
}
}
#pragma endregion 定义的输入输出函数
int main(int argc, char **argv)
{
freopen("cin.txt", "r", stdin);
const unsigned int rowA = 2;
const unsigned int columnA = 3; // columnA必须与rowB相等
const unsigned int rowB = 3;
const unsigned int columnB = 3;
int A[rowA][columnA];
int B[rowB][columnB];
int C[rowA][columnB];
// GP
cout << "GP" << endl;
InputMatrix<rowA, columnA>(A);
InputMatrix<rowB, columnB>(B);
cout << "A=" << endl;
OutputMatrix<rowA, columnA>(A);
cout << endl;
cout << "B=" << endl;
OutputMatrix<rowB, columnB>(B);
cout << endl;
GPMatrixMultiply<rowA, columnA, columnB>(A, B, C); // 必须给常量,编译时确定
cout << "A*B=" << endl;
OutputMatrix<rowA, columnB>(C);
cout << endl;
// flattening the array
cout << "flattening the array" << endl;
InputMatrix<rowA, columnA>(A);
InputMatrix<rowB, columnB>(B);
cout << "A=" << endl;
OutputMatrix<rowA, columnA>(A);
cout << endl;
cout << "B=" << endl;
OutputMatrix<rowB, columnB>(B);
cout << endl;
FlattenMatrixMultiply(*A, *B, *C, rowA, columnA, columnB); // 可运行时给出
cout << "A*B=" << endl;
OutputMatrix<rowA, columnB>(C);
cout << endl;
// struct
cout << "struct" << endl;
Matrix<int> mA(rowA, columnA);
Matrix<int> mB(rowB, columnB);
cin >> mA >> mB;
cout << "A=\n" << mA << endl;
cout << "B=\n" << mB << endl;
cout << "A*B=\n" << StructMatrixMultiply(mA, mB) << endl;
return 0;
}
二、测试数据
1 2 0
2 1 3
2 3 0
1 -2 -1
3 1 1
0 0 0
2 1 3
2 3 0
1 -2 -1
3 1 1
1 2 0
2 1 3
2 3 0
1 -2 0
3 1 0
三、运行结果
GP
A=
1 2 0
2 1 3
B=
2 3 0
1 -2 -1
3 1 1
A*B=
4 -1 -2
14 7 2
flattening the array
A=
0 0 0
2 1 3
B=
2 3 0
1 -2 -1
3 1 1
A*B=
0 0 0
14 7 2
struct
A=
1 2 0
2 1 3
B=
2 3 0
1 -2 0
3 1 0
A*B=
4 -1 0
14 7 0
请按任意键继续. . .