通用二维数组的介绍及分析
首先数组的共性是:
1、连续的存储空间
2、数组元素类型相同(数组元素长度相同)
3、可随即定位(可下标查找)
今天我们设计一个通用的二维数组(用一维数组实现),这个二维数组可以存储不同数据类型的数据,不再受到传统数组数据类型定死的限制!要看代码直接向下滑哦!
INTEGER a(3…10)
上面这条语句是Pascal(一种编程语言)。
由上述语句我们可看到定义数组的真面目,也就是编译系统处理数组的通用原则。只需知道元素类型,开始下标和结束下标就行,因为这些足以计算出数组总空间,从而去申请一段连续的空间。
接下来我想要仿照上面的语句申请一个一维数组并且让它能够实现二维数组的功能!如果掌握了这个方法,不仅仅能够实现二维通用数组,N维都行!当然,前提是你手工过程要好~
手工过程
看下图:

假设有数组定义如下:TYPE ar ( s1…e1 , s2…e2 );且存在 i1 和 i2 在有效下标范围内。求 Loc (ar ( i1, i2 ) ) = Loc (ar) + ? * len 。
这个" ?"显然是在 ar ( i1 , i2 ) 前面的元素个数。想象一个二维数组行数从 s1 到 e1 ,列数从 s2 到 e2 ,此时计算 ar ( i1 , i2 ) 前面的元素个数,我们选用行主序,能得到 " ? " 等于:( i1 - s1 ) * ( e2 - s2 + 1) + ( i2 - s2 ) 。
下图是三维数组公式:

以此类推可以得出及N维数组的(计算给定有效下标的前面元素个数的)公式!

今天我们主要讨论的是二维数组的编写~
( i1 - s1 ) * ( e2 - s2 + 1) + ( i2 - s2 )
注意!上述公式的目的是为了让我们查找数组中指定下标的数据,以及替换指定下标的数据。不是无用的!
开始着手代码编写:
首先需要定义一个二维数组的控制头 ,控制头中包含 ( void **data)(行值) (列值)。void **data 这里定义了一个指针,指针的指类是 void * ,也就是说data指针所指向的空间是一个一维数组,里面存储的是一些四字节指针!而这些指针又指向不同数据类型的数据。我们在这里实现了存储不同数据类型(不同长度)的数据!
了解到这里就上代码八!
matrix.h
#ifndef _MEC_MATRIX_H_
#define _MEC_MATRIX_H_
#include "mec.h"
typedef struct NORMAL_MATRIX {
void **data;
int rowCount;
int colCount;
}NORMAL_MATRIX;
boolean initMatrix(NORMAL_MATRIX **matrix, int rowCount, int colCount);
void destoryMatrix(NORMAL_MATRIX **matrix);
boolean setElementAt(const NORMAL_MATRIX *matrix,
const int row, const int col, void *data);
void *getElementAt(const NORMAL_MATRIX *matrix, const int row, const int col);
#endif
matrix.c
#include <stdio.h>
#include <malloc.h>
#include "mec.h"
#include "matrix.h"
boolean initMatrix(NORMAL_MATRIX **matrix, int rowCount, int colCount) {
if (NULL == matrix || NULL != *matrix || rowCount <= 0 || colCount <= 0) {
return FALSE;
}
*matrix = (NORMAL_MATRIX *) calloc(sizeof(NORMAL_MATRIX), 1);
(*matrix)->data = (void **) calloc(sizeof(void *), rowCount * colCount);
(*matrix)->rowCount = rowCount;
(*matrix)->colCount = colCount;
return TRUE;
}
void destoryMatrix(NORMAL_MATRIX **matrix) {
if (NULL == matrix || NULL == *matrix ) {
return;
}
free((*matrix)->data);
free(*matrix);
*matrix = NULL;
}
boolean setElementAt(const NORMAL_MATRIX *matrix,
const int row, const int col, void *data) {
if (NULL == matrix
|| row < 0 || row >= matrix->rowCount
|| col < 0 || col >= matrix->colCount
|| NULL == data) {
return FALSE;
}
matrix->data[row * matrix->colCount + col] = data;
return TRUE;
}
void *getElementAt(const NORMAL_MATRIX *matrix, const int row, const int col) {
if (NULL == matrix
|| row < 0 || row >= matrix->rowCount
|| col < 0 || col >= matrix->colCount) {
return NULL;
}
return matrix->data[row * matrix->colCount + col];
}
mec.h中定义了boolean 类型,具体请看上一篇博文最底下~
typedef 行为有点像 #define 宏,用其实际类型替代同义字。不同点是 typedef 在编译时被解释,因此让编译器来应付超越预处理器能力的文本替换。