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

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

声明:

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

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

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

概述:

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

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

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

正文:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/353494.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

鼠标爱心显示

/**爱心start**/(function(window,document,undefined){var hearts [];window.requestAnimationFrame (function(){return window.requestAnimationFrame ||window.webkitRequestAnimationFrame ||window.mozRequestAnimationFrame ||window.oRequestAnimationFrame ||window…

多台电脑共用一个耳机、音箱

台式机电脑声卡一般有三个插孔&#xff0c;一个是麦克风&#xff0c;一个是耳机&#xff0c;另一个就是LineIn输入口了&#xff0c;买一根AUX线&#xff0c;一头插入笔记本的耳机插口&#xff0c;另一头插入台式机linein口&#xff1b;在控制面板的声音中选择线路输入&#xff…

liferay开发文档_Liferay –简单主题开发

liferay开发文档实际上&#xff0c;Liferay的6.1版本已经走了很长一段路&#xff0c;该版本完全支持JSF和IceFaces。 我一直在努力学习它的绳索&#xff0c;因为我希望使其成为我们团队中的标准协作工具。 好的软件应用程序可以解决问题&#xff0c;但是好的软件应用程序不仅可…

ACRush 楼天城回忆录

利用假期空闲之时&#xff0c;将这几年 GCJ &#xff0c; ACM &#xff0c; TopCoder 参加的一些重要比赛作个回顾。首先是 GCJ2006 的回忆。 Google Code Jam 2006 一波三折&#xff1a; Google Code Jam 2006 是我第一次到美国参加现场的程序设计比赛。 Google Code Jam 2006…

Matlab计时函数

1. cputime 显示Matlab启动后所占用的CPU时间&#xff1b;eg: t0 cputime; 你的程序&#xff1b;timecputime-t0;2. tic&#xff0c;toc 秒表计时&#xff0c;tic是开始&#xff0c;toc是结束&#xff1b;eg: tic; 你的程序&#xff1b;toc;3. clock&#xff0c;etime 前者显示…

列表,字典表达式以及三元表达式

1.三元表达式条件成立时的返回值 if 条件 else 条件不成立时的返回值三元表达式的意义就是让一些简单的if判断写成一行&#xff0c;减少代码量def max2(x,y): if x > y: return x else: return yx10y20res x if x > y else yprint(res)2.列表生成式…

JUnit 5 –条件

最近&#xff0c;我们了解了JUnit的新扩展模型以及它如何使我们能够将自定义行为注入测试引擎。 我向你保证要看情况。 现在就开始吧&#xff01; 条件允许我们在应该执行或不应该执行测试时定义灵活的标准。 它们的正式名称是“ 条件测试执行” 。 总览 本系列中有关JUnit 5…

我的编程竞赛之路 ——中国大学生计算机编程第一人楼天城访谈

记者/陈秋歌 25岁的楼天城有“中国大学生计算机编程第一人”的称号&#xff0c;也被参加竞赛的学子们敬称为“楼教主”。他的传奇经历一直激励着众多年轻学子&#xff1a;从2001年开始参加计算机编程竞赛&#xff0c;并连获全国一等奖&#xff1b;2004年入选国家集训队&#xf…

MATLAB集合运算

intersect求两个集合的交集ismember检测集合中的元素setdiff求两个集合的差setxor求两个集合交集的非&#xff08;异或&#xff09;union求两个集合的并集unique取集合的单值元素注&#xff1a;交并等操作会对操作结果进行排序

IE8兼容性问题的解决方案

前几天&#xff0c;面试到Ie8的一些兼容问题&#xff0c;傻眼了&#xff0c;回想自己做了将近2年的移动端项目&#xff0c;ie兼容似乎没怎么做过。所以私下便开始找找ie兼容的视频或者文章学习&#xff0c;唉&#xff0c;还是不买书了&#xff0c;家里那么多书&#xff0c;都没…

jenkins部署_Jenkins:部署JEE工件

jenkins部署随着持续集成和持续交付的出现 &#xff0c;我们的构建被分为不同的步骤&#xff0c;以创建部署管道。 这些步骤中的一些步骤可以是例如编译和运行快速测试&#xff0c;运行慢速测试&#xff0c;运行自动验收测试或发布应用程序等。 部署流程的最后步骤意味着将我们…

2013年3月编程语言排行榜:有毒的Java

2013年3月12日&#xff0c;Tiobe公布了新一期编程语言排行榜。Java依旧是占据第一的位置&#xff0c;C语言紧随其后。值得注意的Objective-C持续发力&#xff0c;已经占到了第三的位置。咋一看榜单&#xff0c;前5条中C#下滑最快&#xff0c;从第3名下降到第五名。而其他语言都…

MATLAB各种判断

1. isempty();%判断是否为空2. isnan();%判断是否为NaN3. iscell();%判断是否为元胞数组4. ischar();%判断是否为字符数组5. ismatrix();%判断是否为矩阵6. isrow();%Determine whether input is row vector7. ismember();

js 自定义类Android吐司提示框

(function(){var mouseX 0;var mouseY 0;//定义一个全局toaslist用来存在新建的吐司var toastLsit [];window.Toast function(content,duration,positon){return new Toast(content,duration,positon);}function Toast(content,duration,positon){//显示的内容this.content…

学习Lucene

我目前正在与一个团队合作&#xff0c;开始一个基于Lucene的新项目。 虽然大多数时候我会争论使用Solr还是Elasticsearch而不是简单的Lucene&#xff0c;但这是一个有意识的决定。 在这篇文章中&#xff0c;我正在整理一些学习Lucene的资源–希望您对他们有所帮助&#xff0c;或…

MATLAB递归程序的调试方法

MATLAB具有和VC类似的调试功能&#xff0c;各功能的按钮图标和VC也很相似&#xff0c;基本可以使用VC的调试思想。MATLAB自己的特点&#xff1a;一. 查看中间变量。1. 在调试状态下&#xff0c;鼠标放在变量上就可以显示变量的基本信息。2. 在调试状态下&#xff0c;在命令行输…

DHCP服务(dhcpd)

DHCP动态分配主机地址&#xff08;Dynamic Host Configuration Protocol&#xff09; 动态主机配置协议&#xff08;DHCP&#xff09;是一种基于UDP协议且仅限于在局域网内部使用的网络协议&#xff0c;主要用于大型的局域网环境或者存在较多移动办公设备的局域网环境中&#x…

最健康的睡眠时间究竟是多少?

我每天都睡足8个小时&#xff0c;怎么还是这么困啊&#xff1f;”很多男性朋友都有这样的疑问。不是说每天8个小时的睡眠是最健康的&#xff0c;为什么那些一天睡5、6个小时的人看上去反而更生龙活虎、精力充沛呢&#xff1f; 怪8小时不如6小时的精神 睡眠不足会导致精力不济、…

Matlab Compiler路径

Matlab Compiler run-time找了半天就在自己的安装目录下D:\Program Files\MATLAB\R2011b\toolbox\compiler\deploy\win32\MCRInstaller.ex

EF context.SaveChanges()特点

EF context.SaveChanges()特点1 一次连接保存多条数据&#xff08;工作单元模式&#xff09;&#xff1b;2 内部通过事务来执行&#xff0c;如果一条数据保存失败&#xff0c;执行回滚操作&#xff1b;3 延时加载var userListfrom u in context.UserInfo select u;foreach(var …