任意行列二维数组C语言实现

    在C语言中,数组是一个连续的线性存储结构,数组名称即为数组首元素首地址,中括号被C语言解释为指向运算,通过对指针的加法,实现取得相应元素。对二维数组的使用则相当于定义一个二阶指针,可以看做是一个一维数组里每一个成员是一个一维数组,所以二维数组的名字就是一个指向指针的指针,即二阶指针。通过两次指向运算得到相应的元素。

    但是在C语言中,对变量空间的申请必须要写在一个函数的所有有效语句之前,使得无法得到用户自定义的数组,如果想更改二维数组的行列值不得不更改源代码,具体方式见示例1;

    这种方式显然不符合任意行列二维数组的要求,那么我们想到,既然前面提到二维数组的本质是一个二阶指针,那么,我们是否可以通过用malloc()函数动态申请空间,然后把动态申请的空间的首地址赋值给一个一维数组的每一个元素。但是这样做同样存在问题,我们只能确定二维数组的”列“,并不能确定它的”行“。想要修改行值,依然需要更改源代码。具体代码见示例2;

    所以,想要实现任意行列二维数组,就必须抛弃之前的二阶指针的概念,因为,在C语言中,能够动态申请的空间只能通过malloc()或calloc()函数实现,而它们的返回值都只是(void *)类型的,为一阶指针。因为就算C语言给出了能够申请二维数组的函数,能够返回二阶指针,那如果我想生成一个三维数组怎么办呢,难不成还要给一个返回值为三阶指针的函数么,那如果是n维数组呢......所以我们就必须考虑用一维数组来处理二维数组。其实这也是符合计算机的基本原理的,因为在计算机中内存就是一个二维线性的存储空间,我们看到的二维数组以及二阶指针都是经过C语言处理过的”假象“!既然C语言能够完成,我们自然也可以通过一个简单的数学公式实现用一维数组实现任意行列二维数组。

   

    数学公式基础:1、一个矩阵的元素个数 = 行值 * 列值;

                             2、一个n行m列的矩阵的第i行第j列的元素,为该矩阵的第(i - 1) * n + j个元素(i <= n, j <= m);

    有了这个数学基础,再多考虑C语言中数组下标从零开始这一特点,我们就可以轻松地编写出能够实现任意行列的二维数组的代码!

    由于二维数组不一定只在一个程序中使用。于是我们编写一个.h文件,将初始化二维数组,以及对它的操作的函数写进去,使得以后我们的程序需要用到二维数组的时候只需要在程序的前面加上#include“*.h”即可。

    由于二维数组不一定存放int类型的数据或者某一种特定的数据,有可能是其他类型或者是用户自己定义的结构体类型。因此,在该.h文件里,给出了一个USER_TYPE类型,这就要求在引用该.h文件之前必须先做一个操作。即使用typedef让USER_TYPE成为自己想要的通过二维数组存储的数据类型。

    在之前所说的使用USER_TYPE存储数据,那么便出现了另一个问题,即,无法编写输出该数组的函数,我们不能通过一个简单的printf("%d", USER_TYPE);来输出这一类型,如果USER_TYPE是结构体类型,我们就无法输出了。这里我们通过指向函数的指针来解决,要求用户必须编写一个能够输出一个自己定义的USER_TYPE类型的数据的函数,在使用我们.h文件里编写的二维数组的输出函数的时候,将自己编写的函数的名称作为参数传递过去,而输出二维数组的函数在编写时只需要关注二维数组的整体性输出,每一次的输出,只需要通过形参里的函数指针变量即可,至于该函数是如何输出的,这是使用我们提供的.h文件的人所需要关心的。

    本文章所给的主函数并不具有实际意义,只是对于dyadicArray.h内的函数的调用和测试。

    具体代码如下:

错误示例1:
 
 
#define MAX_ROW     3
#define MAX_COL     4

void main(void) {
    dyadicArray[MAX_ROW][MAX_COL];
}
 
 
错误示例2:
 
 
#include<malloc.h>

#define MAX_ROW

void main(void) {
    int *dyadicArray[MAX_ROW];
    int maxCol;    

    printf("请输入您要得到的数组的列数:");
    scanf("%d", &maxCol);
    for(i = 0; i < MAX_ROW; i++) {
        dyadicArray[i] = (int *)malloc(sizeof(int) * maxCol);
    }
}
 
 
正确代码:
//dyadicArray.h
#ifndef _DYADIC_ARRAY_H_ #define _DYADIC_ARRAY_H_
typedef struct DYADIC_ARRAY{  int row;  int col;  USER_TYPE *array; }DYADIC_ARRAY;
void initDyadicArray(DYADIC_ARRAY **arrayHead, int row, int col); USER_TYPE *getElementByIndex(DYADIC_ARRAY array, int row, int col); void showDyadicArray(DYADIC_ARRAY root, void (* printUserType)(USER_TYPE));
void initDyadicArray(DYADIC_ARRAY **arrayHead, int row, int col) {  *arrayHead = (DYADIC_ARRAY *)calloc(1, sizeof(DYADIC_ARRAY));  (*arrayHead)->row = row;  (*arrayHead)->col = col;  (*arrayHead)->array = (USER_TYPE *)calloc(row * col, sizeof(USER_TYPE)); }
USER_TYPE *getElementByIndex(DYADIC_ARRAY root, int row, int col) {  return root.array + ((row - 1) * root.col + col - 1 - 1); }
void showDyadicArray(DYADIC_ARRAY root, void(*printUserType)(USER_TYPE)) {  int i;  int j;
 printf("该二维数组为:\n");  for (i = 0; i < root.row; i++) {   for (j = 0; j < root.col; j++) {    printUserType(root.array[i * (root.col - 1) + j]);    printf(" ");   }   printf("\n");  } }
#endif
 
 
//demoDyadicArray.c
#include<stdio.h> #include<malloc.h>
typedef struct POINT {  int row;  int col; }POINT, USER_TYPE;
#include"dyadicArray.h"
void showOnePoint(USER_TYPE aPoint);
void showOnePoint(USER_TYPE aPoint) {  printf("(%d, %d)", aPoint.row, aPoint.col); }
void main(void) {  DYADIC_ARRAY *head = NULL;  int row;  int col;  USER_TYPE user;
 user.col = 3;  user.row = 4;
 printf("请分别输入二维数组的行和列:");  scanf_s("%d%d", &row, &col);
 initDyadicArray(&head, row, col);  showDyadicArray(*head, showOnePoint);  *(getElementByIndex(*head, 2, 3)) = user;  showDyadicArray(*head, showOnePoint);
 fflush(stdin);  getchar(); }

 
 
 
 
 
 
 

猜你喜欢

转载自blog.csdn.net/judy_c/article/details/62038688