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

声明:

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

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

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

概述:

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

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

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

正文:

首先,我引用了谭浩强先生编著的《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;
}

如何将二维数组作为函数的参数传递相关推荐

  1. 二维数组作为函数的参数传递

    如何将二维数组作为函数的参数传递,这是涉及到多维数组时经常要遇到的问题.长期来,我们往往知其然,但不知其所以然.这里简单总结一下.     1.<C程序设计>中讲到:可以用二维数组名作为实 ...

  2. C语言中如何将二维数组作为函数的参数传递

    今天写程序的时候要用到二维数组作参数传给一个函数,我发现将二维数组作参数进行传递还不是想象得那么简单里,但是最后我也解决了遇到的问题,所以这篇文章主要介绍如何处理二维数组当作参数传递的情况,希望大家不 ...

  3. php 二维数组去除一项,PHP二维数组提取函数----把不需要的数据剔除

    首先说明一些这个函数的应用场景,比如说你得到的数据是个二维数组,里面的很多成员其实是不必要的,比如说api调用后不必要给别人返回一些用不到的垃圾数据吧,如下是代码. /* * delMemberGet ...

  4. C语言二维数组作为函数参数传递

    二维数组存放方式 二维数组在内存中是按行存放的,先存储第一行,在接着存储第二行-.. 二维数组作为函数参数 二维数组作为函数的参数,实参可以直接使用二维数组名,在被调用函数中可以定义形参所有维数的大小 ...

  5. 二维数组作为函数参数传递

    二维数组作为函数参数调用过程中: void Fun(**a, m, n) {//.... } //.... Fun(a,m,n); 调用函数过程中,会发现VS报错: //IntelliSense: & ...

  6. c语言中怎么用二维数组作为函数参数——来自百度大神

    可以用二维数组名作为实参或者形参,在被调用函数中对形参数组定义时可以指定所有维数的大小,也可以省略第一维的大小说明,如: void Func(int array[3][10]); void Func( ...

  7. 二维数组作为形参的参数传递问题[08-0704]-转

    2008-07-04 19:06 以下是网上摘抄的一段: 首先,我引用了谭浩强先生编著的<C程序设计>上面的一节原文,它简要介绍了如何将二维数组作为参数传递,原文如下(略有改变,请原谅): ...

  8. C语言-二维数组做函数的参数

    文章目录 1 引例 2 观点1 这种使用方法是错误的 3 观点2 根本不需要这么做 4 二维数组做函数参数的方法 4.1 方法1 4.2 方法2 4.3 方法3 5 与Java的不同 1 引例 下面的 ...

  9. 【C 语言】二级指针作为输入 ( 二维数组 | 抽象业务函数 | 二维数组打印函数 | 二维数组排序函数 )

    文章目录 一.抽象 二维数组 业务函数 1.二维数组 打印函数 2.二维数组 排序函数 二.完整代码示例 一.抽象 二维数组 业务函数 1.二维数组 打印函数 注意 , 二维数组 作为 函数参数 输入 ...

最新文章

  1. web 服务器-Nginx
  2. Android 获取屏幕尺寸与密度
  3. python使用集合实现筛选法求素数-python素数筛选法浅析
  4. 清华大学信息 计算机科学与技术,清华大学信息科学与技术国家实验室
  5. 算法与数据结构之判断是否为n的幂
  6. 解决Ubuntu16.04更新源时显示“暂时不能解析域名”问题
  7. 80端口和443端口是什么?有什么区别?
  8. java中pmt计算_5个财务函数FV、PV、PMT、NPER与
  9. java获取当前年第一天_java中如何获取系统时间的当前年份以及年份的第一天和最后一天...
  10. APP——adb命令——背诵实操——背诵总结
  11. windows7创建wlan热点分享网络
  12. 我的世界刷猪人塔java版_我的世界速攻猪人塔详解 史上最牛的经验塔
  13. 如何在谷歌地图自定义范围_如何在Google表格中更改和创建自定义数字格式
  14. 数据增强-亮度-对比度-色彩饱和度-色调-锐度 不改变图像大小
  15. Nokia n97详解
  16. 程序员手把手教你Mac M1Pro的java开发环境安装--jdk、git、maven、及tomcat
  17. 200行代码实现马赛克拼图
  18. 对于Adobe平面设计证书,高级平面设计师,有话说!
  19. JavaScript漂浮广告效果
  20. jquery刷新当前页面、刷新父级页面

热门文章

  1. ftp 传输速度_ftp上传工具下载,8款优秀的ftp上传工具下载软件
  2. 用计算机怎么弹离人愁数字,拇指琴新手入门曲谱——离人愁
  3. 飞畅科技-工业以太网交换机的差异性
  4. 串口服务器常见五大问题解决方案
  5. 【渝粤教育】电大中专药事管理与法规 (2)作业 题库
  6. 【渝粤教育】广东开放大学 数据结构 形成性考核 (30)
  7. 传智杯Java终端有一天您厌烦了电脑上又丑又没用的终端,打算自己实现一个 Terminal
  8. 和显卡驱动要配套吗_天天学渲染,你的显卡驱动用对了吗?
  9. 台电+android+电话,通话系统_台电 G17s_平板电脑评测-中关村在线
  10. 开源项目GoodView点赞效果