这是一种实现方式...我已经将它变得足够通用,以至于它可以处理行数不相等的数组。未填充的点被初始化为零。
MATRIX.h -- MATRIX“对象”的头文件
#ifndef _MATRIX_H_
#define _MATRIX_H_
typedef struct matrix {
int rows;
int cols;
int elemSize;
void *data;
} *MATRIX;
int MATRIX_Create( MATRIX *handlePtr, int initElemSize,
int initRows, int initCols );
int MATRIX_Close( MATRIX *handlePtr );
int MATRIX_Set( MATRIX handle, int row, int col, void *data );
void *MATRIX_GetAddr( MATRIX handle, int row, int col );
int MATRIX_Get( MATRIX handle, int row, int col, void *retData );
int MATRIX_Merge( MATRIX *newHandlePtr, MATRIX leftHandle, MATRIX rightHandle );
#endif
MATRIX.c -- MATRIX“对象”的源文件
#include <stdio.h>
#include <malloc.h>
#include <memory.h>
#include "MATRIX.h"
#define MAX(x,y) ((x > y) ? x : y)
int MATRIX_Create( MATRIX *handlePtr, int initElemSize, int initRows, int initCols )
{
MATRIX handle;
if (handlePtr == NULL)
return (-1);
handle = calloc(sizeof(struct matrix), 1);
if (handle == NULL)
return (-2);
handle->data = calloc(initElemSize, initRows * initCols);
if (handle->data == NULL) {
printf("ERROR -- Could not create MATRIX data area\n");
free(handle);
return (-3);
}
handle->rows = initRows;
handle->cols = initCols;
handle->elemSize = initElemSize;
*handlePtr = handle;
return (0);
}
int MATRIX_Close( MATRIX *handlePtr )
{
if (handlePtr == NULL)
return (-1);
free(*handlePtr);
*handlePtr = NULL;
return (0);
}
int MATRIX_Set( MATRIX handle, int row, int col, void *data )
{
unsigned char *addr;
int addrOffset;
if ((handle == NULL) || (data == NULL))
return (-1);
addr = handle->data;
addrOffset = row * handle->cols * handle->elemSize + (col * handle->elemSize);
addr += addrOffset;
memcpy(addr, data, handle->elemSize);
return (0);
}
void *MATRIX_GetAddr( MATRIX handle, int row, int col )
{
unsigned char *addr;
int addrOffset;
if (handle == NULL)
return (NULL);
addr = handle->data;
addrOffset = row * handle->cols * handle->elemSize + (col * handle->elemSize);
addr += addrOffset;
return (addr);
}
int MATRIX_Get( MATRIX handle, int row, int col, void *retData )
{
unsigned char *addr;
int addrOffset;
if ((handle == NULL) || (retData == NULL))
return (-1);
addr = MATRIX_GetAddr(handle, row, col);
memcpy(retData, addr, handle->elemSize);
return (0);
}
int MATRIX_Merge( MATRIX *newHandlePtr, MATRIX leftHandle, MATRIX rightHandle )
{
int i;
int j;
MATRIX retHandle;
int retCols;
int retRows;
int result;
if ((newHandlePtr == NULL) || (leftHandle == NULL) || (rightHandle == NULL))
return (-1);
/* Ensure that the element sizes for the two matrices to be merged are the same */
if (leftHandle->elemSize != rightHandle->elemSize)
return (-2);
retCols = leftHandle->cols + rightHandle->cols;
retRows = MAX(leftHandle->rows, rightHandle->rows);
result = MATRIX_Create(&retHandle, leftHandle->elemSize, retRows, retCols);
if (result != 0)
return (-3);
/* First copy the left matrix into the merged array */
for (i = 0; i < leftHandle->rows; i++) {
for (j = 0; j < leftHandle->cols; j++) {
result = MATRIX_Set(retHandle, i, j, MATRIX_GetAddr(leftHandle, i, j));
if (result != 0) {
printf("ERROR -- MATRIX_Set() returned %d\n", result);
free(retHandle->data);
free(retHandle);
return (result);
}
}
}
/* And then copy the right matrix into the merged array */
for (i = 0; i < rightHandle->rows; i++) {
for (j = 0; j < rightHandle->cols; j++) {
result = MATRIX_Set(retHandle, i, j+leftHandle->cols, MATRIX_GetAddr(rightHandle, i, j));
if (result != 0) {
printf("ERROR -- MATRIX_Set() returned %d\n", result);
free(retHandle->data);
free(retHandle);
return (result);
}
}
}
*newHandlePtr = retHandle;
return (0);
}
matrix-test.c -- 测试代码的主程序文件
#include <stdio.h>
#include <malloc.h>
#include <memory.h>
#define MAX(x,y) ((x > y) ? x : y)
int MergeArray2D( int **retArrayPtr, int *retRowsPtr, int *retColsPtr,
int *leftArray, int leftRows, int leftCols,
int *rightArray, int rightRows, int rightCols )
{
int *retArray;
int i;
int j;
int retCols;
int retRows;
if ((retArrayPtr == NULL) || (retColsPtr == NULL) || (retRowsPtr == NULL) || (leftArray == NULL))
return (-1);
retCols = leftCols + rightCols;
retRows = MAX(leftRows, rightRows);
retArray = calloc(sizeof(int), retRows * retCols);
if (retArray == NULL)
return (-2);
/* First copy the left array into the merged array */
for (i = 0; i < leftRows; i++) {
for (j = 0; j < leftCols; j++) {
retArray[i * retCols + j] = leftArray[i * leftCols + j];
}
}
/* And then copy the right array into the merged array */
for (i = 0; i < rightRows; i++) {
for (j = 0; j < rightCols; j++) {
retArray[i*retCols + j + leftCols] = rightArray[i * rightCols + j];
}
}
*retArrayPtr = retArray;
*retColsPtr = retCols;
*retRowsPtr = retRows;
return (0);
}
void PrintArray2D( int *array, int numRows, int numCols )
{
int i;
int j;
for (i = 0; i < numRows; i++) {
for (j = 0; j < numCols; j++) {
printf(" %5d", array[i * numCols + j]);
}
printf("\n");
}
}
int main( int argc, char **argv )
{
int leftRows = 5;
int leftCols = 2;
int leftArray[5][2];
int rightRows = 6;
int rightCols = 3;
int rightArray[6][3];
int i;
int j;
int count;
int result;
int *newArray;
int newRows;
int newCols;
MATRIX leftMatrix;
MATRIX rightMatrix;
MATRIX newMatrix;
printf("sizeof(void *) = %d\n", sizeof(void *));
printf("sizeof(int) = %d\n\n", sizeof(int));
count = 0;
/* Initialize the left array */
for (i = 0; i < leftRows; i++) {
for (j = 0; j < leftCols; j++) {
count++;
leftArray[i][j] = count;
}
}
/* Initialize the right array */
for (i = 0; i < rightRows; i++) {
for (j = 0; j < rightCols; j++) {
count++;
rightArray[i][j] = count;
}
}
/* Print out the left array */
printf("Left Array:\n");
PrintArray2D((int *) leftArray, leftRows, leftCols);
/* Print out the right array */
printf("\nRight Array:\n");
PrintArray2D((int *) rightArray, rightRows, rightCols);
/* Merge the two arrays */
result = MergeArray2D(&newArray, &newRows, &newCols, (int *) leftArray, leftRows, leftCols, (int *) rightArray, rightRows, rightCols);
if (result != 0) {
printf("ERROR -- MergeArrays2D() returned %d\n", result);
}
/* Print out the merged array */
printf("\nMerged Array:\n");
PrintArray2D(newArray, newRows, newCols);
/* Clean up the allocated merged array when through using it */
free(newArray);
/* And now for a way of doing the same thing with the MATRIX object */
printf("\n\nTrying same thing using MATRIX object\n\n");
result = MATRIX_Create(&leftMatrix, sizeof(int), leftRows, leftCols);
if (result != 0) {
printf("ERROR -- MATRIX_Create(leftMatrix) returned %d\n", result);
return (result);
}
result = MATRIX_Create(&rightMatrix, sizeof(int), rightRows, rightCols);
if (result != 0) {
printf("ERROR -- MATRIX_Create(rightMatrix) returned %d\n", result);
return (result);
}
/* Initialize the left matrix */
count = 0;
for (i = 0; i < leftMatrix->rows; i++) {
for (j = 0; j < leftMatrix->cols; j++) {
count++;
result = MATRIX_Set(leftMatrix, i, j, &count);
if (result != 0)
printf("ERROR -- Could not set element %d,%d\n", i, j);
}
}
/* Print out the left matrix */
printf("\nLeft Matrix[rows=%d,cols=%d,elemSize=%d]:\n", leftMatrix->rows, leftMatrix->cols, leftMatrix->elemSize);
PrintArray2D(leftMatrix->data, leftMatrix->rows, leftMatrix->cols);
/* Initialize the right matrix */
for (i = 0; i < rightMatrix->rows; i++) {
for (j = 0; j < rightMatrix->cols; j++) {
count++;
result = MATRIX_Set(rightMatrix, i, j, &count);
}
}
/* Print out the right matrix */
printf("\nRight Matrix[rows=%d,cols=%d,elemSize=%d]:\n", rightMatrix->rows, rightMatrix->cols, rightMatrix->elemSize);
PrintArray2D(rightMatrix->data, rightMatrix->rows, rightMatrix->cols);
/* Merge the two matrices */
result = MATRIX_Merge(&newMatrix, leftMatrix, rightMatrix);
if (result != 0) {
printf("ERROR -- MATRIX_Merge() returned %d\n", result);
return (result);
}
/* Print out the new matrix */
printf("\nMerged Matrix[rows=%d,cols=%d,elemSize=%d]:\n", newMatrix->rows, newMatrix->cols, newMatrix->elemSize);
PrintArray2D(newMatrix->data, newMatrix->rows, newMatrix->cols);
/* Cleanup the newMatrix when finished */
result = MATRIX_Close(&newMatrix);
}
测试程序的输出:
sizeof(void *) = 4
sizeof(int) = 4
Left Array:
1 2
3 4
5 6
7 8
9 10
Right Array:
11 12 13
14 15 16
17 18 19
20 21 22
23 24 25
26 27 28
Merged Array:
1 2 11 12 13
3 4 14 15 16
5 6 17 18 19
7 8 20 21 22
9 10 23 24 25
0 0 26 27 28
Trying same thing using MATRIX object
Left Matrix[rows=5,cols=2,elemSize=4]:
1 2
3 4
5 6
7 8
9 10
Right Matrix[rows=6,cols=3,elemSize=4]:
11 12 13
14 15 16
17 18 19
20 21 22
23 24 25
26 27 28
Merged Matrix[rows=6,cols=5,elemSize=4]:
1 2 11 12 13
3 4 14 15 16
5 6 17 18 19
7 8 20 21 22
9 10 23 24 25
0 0 26 27 28
为了使其成为通用解决方案,我将 2D 数组视为 1D 数组,因为这就是它们在内存中的布局方式。如果你不想要一个通用的解决方案,你应该很容易修改代码,你不会有太多的参数需要传递给 MergeArray2D 函数。
编辑:
我通过创建矩阵“对象”的“C”版本添加了一个更通用的解决方案,就像我通过休斯顿的一个航空航天承包商为 NASA 工作时在后面实现“对象”一样。我还将“对象”的头文件和源文件拆分为单独的代码窗口,以便于阅读。对于任何 C++ 人来说,将其转换为 C++ 类可能都是一件小事,但我认为从教学的角度来看,直接使用“C”会更好。这个“对象”允许使用不同于第一个示例中使用的“int”的不同基本元素数据大小来“实例化”它。我已经在 PC 上使用 gcc 测试了代码,它实际上可以正确编译和运行。希望这会有所帮助...