Here's a way of doing it... I've made it generic enough that it can handle arrays that are not of an equal number of rows. The unfilled spots are initialized as zero.
MATRIX.h -- Header file for the MATRIX 'object'
#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 -- Source file for the MATRIX 'object'
#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 -- main program file for test code
#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);
}
Output from the test program:
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
To make this a generic solution, I'm treating the 2D arrays as just a 1D array since that is how they are laid out in memory anyway. If you don't want a generic solution, it should be easy for you to modify the code and you won't have as many parameters that need to be passed into the MergeArray2D function.
EDITED:
I've added an even more generic solution by creating the 'C' version of a MATRIX 'object' like we used to implement 'objects' in back when I worked for NASA via one of the aerospace contractors here in Houston. I've also split the header and source files for the 'object' into separate code windows to make it easier to read. For any of the C++ folks, it will probably be a trivial matter to convert that to a C++ class, but I think straight 'C' is better from a teaching standpoint. This 'object' allows for it to be 'instantiated' with a different base element data size other than 'int' which was used in the first example. I have tested the code using gcc on a PC and it does in fact compile and run correctly. Hope this helps...