`
thomas0988
  • 浏览: 484866 次
  • 性别: Icon_minigender_1
  • 来自: 南阳
社区版块
存档分类
最新评论

如何将二维数组作为函数的参数传递

阅读更多

如何将二维数组作为函数的参数传递
    作者: jatix
    邮箱: jatix@163.com
    QQ:   52287017

声明:

  如果你是得道的大侠,这篇文章可能浪费你的时间,如果你坚持要看,我当然感觉很高

兴,但是希望你看完了别骂我!如果你发现我这篇文章有错误的话,你可以提出批评以及

指正,我将很乐意地接受。*_*

概述:

  今天写程序的时候要用到二维数组作参数传给一个函数,我发现将二维数组作参数进行

传递还不是想象得那么简单里,但是最后我也解决了遇到的问题,所以这篇文章主要介绍

如何处理二维数组当作参数传递的情况,希望大家不至于再在这上面浪费时间。

正文:

  首先,我引用了谭浩强先生编著的《C程序设计》上面的一节原文,它简要介绍了如何

将二维数组作为参数传递,原文如下(略有改变,请原谅):

  [原文开始]

    可以用二维数组名作为实参或者形参,在被调用函数中对形参数组定义时可以可以指

定所有维数的大小,也可以省略第一维的大小说明,如:
    void Func(int array[3][10]);
    void Func(int array[][10]);
    二者都是合法而且等价,但是不能把第二维或者更高维的大小省略,如下面的定义是

不合法的:
    void Func(int array[][]);
    因为从实参传递来的是数组的起始地址,在内存中按数组排列规则存放(按行存放),

而并不区分行和列,如果在形参中不说明列数,则系统无法决定应为多少行多少列,不能

只指定一维而不指定第二维,下面写法是错误的:
    void Func(int array[3][]);实参数组维数可以大于形参数组,例如实参数组定义为


    void Func(int array[3][10]);
    而形参数组定义为:
    int array[5][10];
    这时形参数组只取实参数组的一部分,其余部分不起作用。

  [原文结束]

  大家可以看到,将二维数组当作参数的时候,必须指明所有维数大小或者省略第一维的

,但是不能省略第二维或者更高维的大小,这是由编译器原理限制的。大家在学编译原理

这么课程的时候知道编译器是这样处理数组的:

  对于数组 int p[m][n];
  如果要取p[i][j]的值(i>=0 && i<m && 0<=j && j < n),编译器是这样寻址的,它的

地址为:
  p + i*n + j;

  从以上可以看出,如果我们省略了第二维或者更高维的大小,编译器将不知道如何正确

的寻址。但是我们在编写程序的时候却需要用到各个维数都不固定的二维数组作为参数,

这就难办了,编译器不能识别阿,怎么办呢?不要着急,编译器虽然不能识别,但是我们

完全可以不把它当作一个二维数组,而是把它当作一个普通的指针,再另外加上两个参数

指明各个维数,然后我们为二维数组手工寻址,这样就达到了将二维数组作为函数的参数

传递的目的,根据这个思想,我们可以把维数固定的参数变为维数随即的参数,例如:

    void Func(int array[3][10]);
    void Func(int array[][10]);
  变为:
    void Func(int **array, int m, int n);

  在转变后的函数中,array[i][j]这样的式子是不对的(不信,大家可以试一下),因为

编译器不能正确的为它寻址,所以我们需要模仿编译器的行为把array[i][j]这样的式子

手工转变为

    *((int*)array + n*i + j);

    在调用这样的函数的时候,需要注意一下,如下面的例子:
    int a[3][3] =
    {
      {1, 1, 1},
      {2, 2, 2},
      {3, 3, 3}
    };
    Func(a, 3, 3);

  根据不同编译器不同的设置,可能出现warning 或者error,可以进行强制转换如下调用

: 
    Func((int**)a, 3, 3);

  其实多维数组和二维数组原理是一样的,大家可以自己扩充的多维数组,这里不再赘述

。写到这里,我先向看了这篇文章后悔的人道歉,浪费你的时间了。下面是一个完整的例

子程序,这个例子程序的主要功能是求一个图中某个顶点到其他顶点的最短路经,图是以

邻接矩阵的形式存放的(也就是一个二维数组),其实这个函数也是挺有用的,但是我们这

篇文章的重点在于将二维数组作为函数的参数传递。

  完整的例子程序包括三个文件,在Microsoft Visual C++ 6.0下调试通过。如下:

  //
  // mian.c 为主程序入口,并且调用了示范了如何调用求一个图中某个顶点到其他顶点

的最短路经
  // 的函数
  //
 #include "short.h"
 #include <stdio.h>
 
 int main()
 {
  int i = 0, v = 0;
  
  float AdjoinMatrix[5][5]=
  {
   {0, 10,NO_PATH,30,100},
   {NO_PATH,0,50,NO_PATH,NO_PATH},
   {NO_PATH,NO_PATH,0,NO_PATH,10},
   {NO_PATH,NO_PATH,20,0,60},
   {NO_PATH,NO_PATH,NO_PATH,NO_PATH,0}
  };
  int Path[5];
  float Length[5];
  
  ShortestPath(AdjoinMatrix, Length, Path, 5, 0);
  
  for(i = 1; i < 5; i++)
  {
   v = i;
   while(v != 0)
   {
    printf("%d ", v);
    v = Path[v];
   }
   printf("%d\n", v);
  }
  return 0;
 }

  //
  // ShortestPath.h 中定义了求一个图中某个顶点到其他顶点的最短路经的函数,还定

义了一个
  // 宏,#define  NO_PATH 0x00ffffff,如果图中的两个顶点之间的直接路径的长度为

NO_PATH,
  // 表示图中两个顶点是不直接相通的。
  //

 #ifndef INCLUDE_SHORTESTPATH_H
 #define INCLUDE_SHORTESTPATH_H
 
 #define IN
 #define OUT
 
 #define  NO_PATH 0x00ffffff
 
 
 /*++
 Abstract:
 
   该函数的功能是求得一个图中的某个顶点到其他所有顶点的最短路经,及其最

短路经的长度
  
  Returen value:
  
    类型是int,含义如下
    0 成功
    1   资源不够
   
   Examples:
   
     //你有一个图的邻接矩阵如AdjoinMatrix[n][n]和数组

Path[n], Length[n](n为图顶点的个数,
     //然后你可以如下调用:ShortestPath(AdjoinMatrix,

Length, Path, 5, 0);
     //调用后,Path[n]中存放最短路径,Length[n]中存放着最

短路径的长度
     //下面的例子中我们求得从0顶点到其他定点的最短路经及

其长度
    
    float AdjoinMatrix[5][5]=
    {
    {0, 10,NO_PATH,30,100},
    {NO_PATH,0,50,NO_PATH,NO_PATH},
    {NO_PATH,NO_PATH,0,NO_PATH,10},
    {NO_PATH,NO_PATH,20,0,60},
    {NO_PATH,NO_PATH,NO_PATH,NO_PATH,0}
    };
    int Path[5];
    float Length[5];
    
      ShortestPath(AdjoinMatrix, Length, Path, 5,

0);
     
     int i = 0, int v =0;
     for(i = 1; i < 5; i++)
     {
     v = i;
     while(v != 0)
     {
     printf("%d ", v);
     v = Path[v];
     }
     printf("%d\n", v);
     }
     
 --*/
 
 int ShortestPath(
  IN  float **AdjoinMatrix,  //存放图的邻接矩阵,是

一个二维数组
  OUT float *Length,    //用于返回到各

个点的最短路经的长度
  OUT int   *Path,    //用于返回最短

路经,Path[i]表示在最短路经上顶点i前面的顶点
  IN  int   VertexNum,   //顶点的个数
  IN  int   Vertex    //起始顶点
  );
 #endif


  //
  // ShortestPath.c 中实现了求一个图中某个顶点到其他顶点的最短路经的函数。
  //
 
 #include "ShortestPath.h"
 
 #include <stdlib.h>
 
 
 /*++
 Abstract:
 该函数的功能是求得一个图中的某个顶点到其他所有顶点的最短路经,及其最短

路经的长度
 Returen value:
 类型是int,含义如下
 0 成功
 1   资源不够
 --*/
 
 int ShortestPath(
  IN  float **AdjoinMatrix,  //存放图的邻接矩阵,是

一个二维数组
  OUT float *Length,    //用于返回到各

个点的最短路经的长度
  OUT int   *Path,    //用于返回最短

路经,Path[i]表示在最短路经上顶点i前面的顶点
  IN  int   VertexNum,   //顶点的个数
  IN  int   Vertex    //起始顶点
  )
 {
  int i = 0, j = 0, w = 0;
  
  //
  // 已经在最短路经中的点的集合,如果VertexSet[i]不为0,则表示第

i个点在该集合中
  //
  int *VertexSet = (int*)malloc(VertexNum);
  if(VertexSet == NULL)
  {
   return 1; //缺乏内存资源
  }
  
  //
  // 初始化
  //
  for(i = 0; i < VertexNum; i++)
  {
   Length[i] = *((float*)AdjoinMatrix + Vertex*VertexNum

+ i);
   VertexSet[i]=0; 
   if(i != Vertex && Length[i] < NO_PATH)
   {
    Path[i]=Vertex;
   }
   else
   {
    Path[i] = -1;
   } 
  }
  VertexSet[Vertex] = 1;
  Length[Vertex] = 0;
  
  //
  // 求得最短路经
  //
  for(i = 0; i < VertexNum-1; i++)
  {
   float min = NO_PATH;
   int u = Vertex;
   for(j = 0; j < VertexNum; j++)
   {
    if( !VertexSet[j] && Length[j] < min)
    {
     u = j;
     min = Length[j];
    }
   }
   VertexSet[u] = 1;
   for(w = 0; w < VertexNum; w++)
   {
    if(!VertexSet[w] && *((float*)AdjoinMatrix +

u*VertexNum + w) < NO_PATH && Length[u]+*((float*)AdjoinMatrix + u*VertexNum +

w) < Length[w])
    {
     Length[w] = Length[u] +

*((float*)AdjoinMatrix + u*VertexNum + w);
     Path[w] = u;
    }
   }
  }
  
  return 0;
 }

分享到:
评论

相关推荐

    C语言中二维数组作为函数参数来传递的三种方法

    今天,我们将详细介绍C语言中二维数组作为函数参数来传递的三种方法。 方法一:形参给出第二维的长度 在这种方法中,我们可以在函数参数中指定第二维的长度。例如: ```c void func(int n, char str[][5]) { int ...

    二维数组作为函数形参的两种方法

    本篇文章将深入探讨如何将二维数组作为函数的形参进行传递,以实现特定的功能,例如本例中的二维数组求和。我们将讨论两种主要的方法:通过指针和通过引用。 ### 方法一:通过指针传递二维数组 在C++中,数组名...

    调用形参为二维数组的函数

    接下来,我们需要了解如何将这个动态创建的二维数组作为参数传递给一个接受二维数组作为形参的函数。在C/C++中,数组名在函数调用中通常被视为指向数组首元素的指针。因此,传递二维数组的行首地址可以模拟传递整个...

    JNA调用C++动态库,传入二维数组,通过C++返回二维数组,java调用C++完整案例

    在C++中,你可能需要提供一个辅助函数来处理Java传递过来的一维数组,转换为C++的二维数组格式。 此外,对于大型数据结构,考虑到性能问题,可能需要考虑使用直接内存映射(Direct Memory Mapping)或者自定义类型...

    C/C++中多维数组指针作为函数参数传递程序

    在 `main` 函数中,我们将二维数组 `a` 作为参数传递给 `search_score` 和 `count_avg` 函数。例如,`search_score(a,0)` 就是将二维数组 `a` 的第一个元素作为参数传递给 `search_score` 函数。 在 `search_score`...

    C语言二维数组编程练习

    本编程练习旨在加深对C语言中二维数组、指针和函数的理解,通过实际操作提升编程技能。下面我们将深入探讨这些知识点。 首先,二维数组在C语言中被声明为`类型名 数组名[行数][列数]`,例如`int arr[3][4]`创建了一...

    读取二维数组所有数据_labview读取数组_

    1. **创建二维数组**: 在LabVIEW的函数选板中,找到“数值”类别,然后选择“数组”子类别。在这里,你可以找到“创建数组”VI,它可以用来创建一个指定大小的二维数组。你需要提供行数和列数作为输入,然后默认填充...

    C++动态二维数组的申请、赋值、使用、释放以及作参数示例

    动态二维数组还可以作为函数参数传递,下面的示例展示了如何定义一个接受动态二维数组作为参数的函数: ```cpp void display(int **&p, int row, int col) { for (int i = 0; i ; i++) { for (int j = 0; j ; j++...

    c#调用c++DLL,dll有二维数组

    在C++中,创建一个二维数组函数可能如下所示: ```cpp extern "C" __declspec(dllexport) void get2DArray(int*** arr, int& rows, int& cols) { // 初始化二维数组并设置rows和cols *arr = new int*[rows]; ...

    二维数组与二重指针(整理)

    在函数中传递二维数组作为参数时,需要指定第二维的下标,例如 `void trans(int a[][3], int b[])`。这时,函数 `trans` 可以正确地访问和修改二维数组 `a`。 动态申请二维数组作为参数传递进函数里的方法是使用...

    C++二维数组编程实例.zip

    二维数组可以作为函数的参数进行传递,但需要注意的是,数组名实际上代表数组的首地址,因此传递数组时实参和形参类型应一致,如: ```cpp void printArray(int arr[3][4]) { // 打印数组代码 } int main() {...

    第7章数组作为函数参数.ppt

    在编程中,数组是存储一组相同类型数据的集合,而在函数调用中,有时我们需要将数组作为参数传递给函数来处理。本章主要探讨的是如何在C语言中使用数组作为函数参数。 首先,我们来看一维数组参数的定义和使用。在...

    二维数组的行列互换(函数调用实现)

    实现数组的行列互换 形参使用二维数组。函数调用使用引用传递,比较基础。

    C语言编程技术实践2020版 数组作为函数参数翻转课堂教学设计.docx

    课后学习任务则延伸到实验和作业,学生需要完成相关练习以巩固所学,如二维数组的操作,并预习实验内容,提前编写程序,以准备实验环节。此外,资源库课程平台提供了丰富的实践文档,供学生自主学习。 总的来说,这...

    函数、内存、一维数组、二维数组

    形式参数:是一个变量,用于存储调用函数时传递给函数的实际参数。 实际参数:传递给形式参数的具体数值。 return:用于结束函数。 返回值:该函数运算后的结果,该结果会返回给调用者。 函数的特点 ...

    C代码之二维参数(数据结构)

    因此,有两种主要的方法可以将二维数组作为参数传递给函数: 1. **传递数组名**: - 这种方式实际上是传递数组的基地址,即首行的首地址。 - 函数定义时可以使用形参形式`int (*p1)[column_size];`,这里`p1`是一...

    编写一个在具有m行n列的二维数组各元素中找出最大元和最小元并显示在屏幕上的函数模板,并通过主函数对它进行调用以验证其正确性。例如,可设计该函数模板的原型为:

    注意:函数模板maxMin中要处理二维数组A的m行n列的诸元素,但设计第一参数传递过来的是Type*类型的首元素指针,所以具体处理时可以按照如下的“一维数组”方式来进行(共处理m乘以n个数据 -- 也即二维数组A的m行n列...

Global site tag (gtag.js) - Google Analytics