《程序设计基础》课件第7章_第1页
《程序设计基础》课件第7章_第2页
《程序设计基础》课件第7章_第3页
《程序设计基础》课件第7章_第4页
《程序设计基础》课件第7章_第5页
已阅读5页,还剩80页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第7章数组7.1一维数组

7.2函数间一维数组的传递

7.3二维数组

7.4函数间二维数组的传递

习题

7.1一维数组

7.1.1数组概述

通过前面的学习,我们知道,如果在程序中需要暂时存放几个数据,就需要定义几个变量。但是,这种方法在处理大批量的同类型的数据的时候,就显得不是很方便了。例如,某个班级有45名同学,在“程序设计基础”这门课程考试结束后,要编写一个程序,统计一下成绩高于平均分的人数。针对这个问题,可以设计出如下算法:

①依次接受并暂存45个成绩;

②计算总分和平均分;③置计数器为0;

④对每一个成绩,若它大于平均分,则计数器累加1;

⑤输出计数器的值。

按照以上算法的要求,如果在程序中定义45个变量去暂存这45个成绩,显然是一种比较笨拙的办法。

那么,有没有更好的办法呢?其实,针对这种大批量数据的存储问题,C语言中提供了数组这种数据类型来解决。数组的实质是内存中一段连续的存储空间,例如内存中连续的20个字节的存储空间就可以称为一个数组。这个数组如果用来存放int型的数据,则可以存放10个(若每个int型的数据需要两个字节的存储空间)。此时每两个字节构成数组中一个存储单元,称为数组元素或数组分量;当然,这个数组也可以用于存放5个float型的数据(若每个float型的数据需要4个字节的存储空间),此时,每4个字节构成一个数组分量。在程序中,数组用一个名字来表示,数组中分量用编号来区分。采用这种方式,不但解决了大批量同类型数据的存储问题,而且方便用循环的方式来对这些数据进行运算和处理。存放在数组中的多个数据,从逻辑上可以看做是按一个方向排列的,也可以看做是按两个方向排列的。例如20个整数可以看做是按一个方向排列的,在C语言中称为一维数组;这20个整数也可以分为4组,每组5个,在C语言中就称为二维数组。这种情况下,通常仿照数学中行列式的形式,称这20个数构成4行5列的二维数组。当然,一组数也可以看做是按多个方向排列的,这在C语言中就称为多维数组了。7.1.2一维数组的定义和初始化

一维数组的定义形式如下:

数据类型数组名[分量个数];

数组名和变量名一样,是C语言中的标识符,必须符合标示符的命名规则。分量个数必须是一个整型数,通常是常量或常量表达式。分量个数表示的数组中存储单元的个数,也就是这个数组中可以最多存放的数据的个数。数据类型用来指定数组中可以存放的数据的类型。例如:

intarray[10];以上语句,定义array是一个数组,这个数组是用来存放int型数据的,最多可以存放10个int型的数据。

定义了数组之后,如果这个数组是外部数组,则数组中每个分量中存放的都是0,也就是说,每个数组元素的值都是0;如果这个数组是内部数组,则数组中元素的值是随机值。定义数组时,可以把特定的值存放在数组中,这种情况称为数组的初始化,例如:

intarray[10]={1,2,3,4,5,6,7,8,9,10};以上语句,定义array是一个有10个元素的int型数组,同时把1,2,3,…,10这10个数依次存放在数组的10个元素中。当然,也可以对数组进行部分初始化,例如:

intarray[10]={1,2,3};

以上语句,在定义数组的同时,把1、2、3依次存放在数组的第1、第2和第3个元素中,此时,数组中其余元素自动被初始化为0。7.1.3一维数组元素的引用

数组在使用中,通常不会做整体的引用,更多的是引用数组中某一个分量中存放的数据。一维数组中的每一个分量都对应一个编号。需要特别注意的是分量的编号是从0开始的,即数组中第一个分量的编号为0,第二个分量的编号为1,依此类推。在程序中,引用数组分量的形式为“数组名[编号]”,这里的编号为一个取值为int型的表达式。例如,对如下定义的数组:

intarray[10];如果要将其中的第1个分量赋值为5,则表达为如下语句:

array[0]=5;

再例如要将数组array中第3个分量和第4个分量中存放的值求和后,存放在数组的第5个分量中,可使用如下语句:

array[4]=array[2]+array[3];

在对数组中存放的数据进行运算和处理时,通常采用循环的方式,例如对于前面提到的成绩统计的问题,可以编写出如下的源程序:/*源程序7-1*/

#include"stdio.h"

main()

{

floatscore[45],sum,avg;

inti,counter;

for(i=0;i<45;i++){

printf("Paleaseinputscore[%d]:",i);

scanf("%d",&score[i]);

}

sum=0;

for(i=0;i<45;i++)

sum+=score[i];

avg=sum/45;

counter=0;

for(i=0;i<45;i++)

if(score[i]>avg)

counter++;

printf("counter=%d\n",counter);

}7.1.4简单排序算法

排序问题是计算机编程中的一个常见问题。在日常的数据处理中,面对大量的数据,也许有成百上千种的处理要求,而这些处理往往是以排序作为前提的。例如查找,在有序的数据中进行查找,当然比在无序的数据中进行查找要容易得多。在计算机发展的历史中,前人为我们留下了很多经典的排序算法,它们都是智慧的结晶。下面就讨论其中比较简单的两种排序算法。首先把排序的问题具体化:假如有10个整数,按照任意次序存放在计算机的一段连续内存(为了描述方便,把这一段连续内存看做是有10个分量的一维数组array)中,我们要做的就是将array数组中的这10个数的存放位置调整为由大到小。下面先看第一种简单排序方法,选择排序法。

针对前面所描述的问题,可以采用如下算法来解决:

(1)从array[0]至array[9]中找出一个最大的数,假如这个数在array[max_index]中,把它交换到数组的第一个位置,即array[max_index]与array[0]交换;

(2)从array[1]至array[9]中找出一个最大的数,假如这个数在array[max_index]中,把它交换到数组的第一个位置,即array[max_index]与array[1]交换;

(3)从array[2]至array[9]中找出一个最大的数,假如这个数在array[max_index]中,把它交换到数组的第一个位置,即array[max_index]与array[2]交换;

……

(9)从array[8]至array[9]中找出一个最大的数,假如这个数在array[max_index]中,把它交换到数组的第一个位置,即array[max_index]与array[8]交换。

以上的算法,用伪代码的形式描述如下:

for(i=0;i<=9;i++){

从array[i]至array[9]中找出一个最大的数,假如这个数在array[max_index]中,

把它交换到数组的第一个位置,即array[max_index]与array[i]交换;

}

我们再把从array[i]至array[9]中找最大数的算法和交换的算法细化,得到如下算法描述:for(i=0;i<=8;i++){

max_index=i;

for(j=max_index+1;j<=9;j++)

if(array[j]>array[max_index])

max_index=j;

if(max_index!=i){

t=array[i];

array[i]=array[max_index];

array[max_index]=t;

}下面给出一个完整的源程序,程序中的10个数是调用随机函数生成的100以内的数。

/*源程序7-2*/

#include"stdio.h"

#include"stdlib.h"

main()

{

intarray[10],i,j,t,max_index;

for(i=0;i<=9;i++)

array[i]=rand()%100;

printf("Beforesorting:\n");

for(i=0;i<=9;i++)

printf("%d\t",array[i]);

for(i=0;i<=8;i++){

max_index=i;

for(j=max_index+1;j<=9;j++)

if(array[j]>array[max_index])

max_index=j;

if(max_index!=i){ t=array[i];

array[i]=array[max_index];

array[max_index]=t;

}

}

printf("\nAftersorting:\n");

for(i=0;i<=9;i++)

printf("%d\t",array[i]);

}程序运行结果如下:

上面的程序中,每一次都是通过比较先找到最大数所在位置的编号max_index,然后再进行交换。还可以把比较的过程和最后的交换结合起来,也就是在比较的过程中完成交换,这样,源程序可以修改成如下形式:/*源程序7-3*/

#include"stdio.h"

#include"stdlib.h"

main()

{

intarray[10],i,j,t;

for(i=0;i<=9;i++)

array[i]=rand()%100;

printf("Beforesorting:\n");

for(i=0;i<=9;i++)

printf("%d\t",array[i]);

for(i=0;i<=8;i++){

for(j=i+1;j<=9;j++)

if(array[j]>array[i]){

t=array[i];

array[i]=array[j];

array[j]=t;

}

}

printf("\nAftersorting:\n");

for(i=0;i<=9;i++)

printf("%d\t",array[i]);

}选择排序法之所以叫做选择排序法,就是因为这种方法每次选出一个合适的数,放到合适的位置上。很容易就可以推知,对n个数进行排序,共需要n-1次这样的选择。

下面再来看另一种简单排序算法,这种排序算法有一个非常有趣的名字,叫做冒泡排序。为什么叫做冒泡排序呢?还是以前面给出的问题为例来说明。

要对数组array中存放的10个整数排序,首先对array数组做一遍这样的处理:

从array[0]至array[9],相邻的两个数依次比较,即array[0]与array[1]比较,array[1]与array[2]比较,…,array[8]与array[9]比较,在比较的过程中,如果前面的数小于后面的数,则交换两个数的位置。通过这样一遍处理,虽然整个数组还是没有顺序的,但是最小的一个数在比较的过程中被逐渐的后移,最终被交换到最后一个位置了。这个过程有点像水里的气泡从水底逐渐地浮到水面的过程,所以这种排序算法叫做冒泡排序法。然后,使用同样的方法,依次对array[0]至array[8]、array[0]至array[7]、…、array[0]至array[1]做同样的处理。前后共做9次这样的处理,就可以得到由大到小的次序。这个过程用伪代码描述为:

for(i=9;i>=1;i--){

从array[0]至array[i],相邻的两个数依次比较,如果前面的数小于后面的数,则交换两个数的位置。

}对相邻两个数比较并交换的算法进行细化,得到如下算法描述:

for(i=9;i>=1;i--){

for(j=0;j<=i-1;j++){

若array[j]<array[j+1],则交换array[j]与array[j+1];

}

}

下面,给出完整的源程序:/*源程序7-4*/

#include"stdio.h"

#include"stdlib.h"

main()

{

intarray[10],i,j,t;

for(i=0;i<=9;i++)

array[i]=rand()%100;

printf("Beforesorting:\n");

for(i=0;i<=9;i++)

printf("%d\t",array[i]);for(i=9;i>=1;i--)

for(j=0;j<=i-1;j++)

if(array[j]<array[j+1]){

t=array[j];

array[j]=array[j+1];

array[j+1]=t;

}

printf("\nAftersorting:\n");

for(i=0;i<=9;i++)

printf("%d\t",array[i]);

}程序运行结果如下:

7.2函数间一维数组的传递

7.2.1一维数组元素地址的表示

在前面一章中介绍了指针的概念,我们知道指针就是地址,数据的指针就是数据的地址。在C语言中,地址可以和整型数进行加、减法运算。首先需要明确的是地址和整型数进行加、减运算的结果还是地址。下面,先看一个程序实例:/*源程序7-5*/

#include"stdio.h"

main()

{

intarray[10];

if(&array[0]+1==&array[1])

printf("&array[0]+1==&array[1]\n");

else

printf("&array[0]+1!=&array[1]\n");

}程序运行结果如下:

以上程序的运行结果说明,&array[0]+1的结果还是一个地址,这个地址就是&array[1]的地址。当然,&array[1]-1的结果就是&array[0]。也就是说,一个数据的地址加1或减1,得到的是后一个或前一个数据的地址。由此可以推知在数组array中,&array[0]+i(0≤i≤9)等价于&array[i],进一步讲,*(&array[0]+i)等价于array[i]。7.2.2利用指针变量访问一维数组

C语言程序中的一维数组对应的是计算机内存中一段连续的内存。而数组的名字,实质是一个地址常量,这个地址常量和数组首元素的地址是相同的。下面看一个程序的例子:/*源程序7-6*/

#include"stdio.h"

main()

{

intarray[10];

if(array==&array[0])

printf("arrayequal&array[0]\n");

else

printf("arraydon'tequal&array[0]\n");

}程序运行结果如下:

以上程序的运行结果证明了在C语言中数组的名字确实等价于数组首元素的地址,即在以上程序中,array等价于&array[0]。结合前面的结论可以得出,在以上程序中,有如下等价关系:

array+i 等价于&array[i]

*(array+i)等价于array[i]其实,“array[i]”这种形式,可以看做是“*(array+i)”的简略形式。从而可以得到一个结论:“*(地址+i)”这种形式的表达式可以等价地写成“地址[i]”这种简略形式。而这个地址,既可以是地址常量,如数组名,也可以是地址变量,也就是指针变量。比如下面的程序:/*源程序7-7*/

#include"stdio.h"

main()

{

intarray[10]={1,2,3,4,5,6,7,8,9,10},i;

int*p;

p=array;

for(i=0;i<10;i++)

printf("%d\t",p[i]);

printf("\n");

}程序运行结果如下:

以上程序中,语句“p=array;”把数组首元素的地址赋给了指针变量p,从而使在程序中p与&array[0]等价。由此得到以下等价关系:

p+i 等价与&array[0]+i

*(p+i)等价于*(&array[0]+i)

p[i]等价于array[i]

把上面的结论简单地归纳一下:在程序中,当把一个一维数组首元素的地址赋给一个指针变量时,这个指针变量就可以当做这个一维数组的名字来使用。7.2.3在函数间传递一维数组

函数是一段相对独立的程序代码,其功能是进行数据的处理和加工。它所处理和加工的数据的来源通常就是函数的形式参数,其处理结果就是函数的返回值。也就是说,函数调用时,被调函数通过形式参数从主调函数中获取需要处理和加工的数据,经过加工和处理后,再以返回值的形式传递给主调函数,做进一步的处理。那么,当主调函数需要把一个一维数组交给被调函数时,应该如何解决呢?一种办法就是主调函数把一维数组中每一个元素的值传递给被调函数,这就意味着数组中有多少个元素,被调函数就要定义多少个形式参数,显然这不是一个好办法。其实,因为一维数组在内存中是连续的,主调函数只需要把数组首元素的地址传递给被调函数,通过这个地址,被调函数就可以访问到这个一维数组中的所有元素了。当然这里还有一个问题,就是被调函数只获得一维数组首元素的地址是不够的,它还必须获得一维数组元素的个数。否则,它知道这个一维数组从哪里开始,而不知道在哪里结束,也是不能正确地访问这个一维数组的。通过上面的分析可知,当主调函数要把一个一维数组传递给被调函数的时候,要向被调函数传递两个值:数组首元素的地址和数组元素的个数。那么,被调函数的形式参数对应的就应该是一个指针变量和一个普通变量,而在被调函数中,这个指针变量是被当做一维数组来使用的。下面看一个程序的例子,这个程序的功能是将一个一维数组中存放的数据逆置,即数组中第一个元素和最后一个元素交换位置,第二个元素与倒数第二个元素交换位置,依次类推。/*源程序7-8*/

#include"stdio.h"

voidreversal(int*p,intn)

{

inti,j,t;

for(i=0,j=n-1;i<j;i++,j--){

t=p[i];

p[i]=p[j];

p[j]=t;

}}

main()

{

intarray[10]={1,2,3,4,5,6,7,8,9,10},i;

printf("Beforereversal:\n");

for(i=0;i<10;i++)

printf("%d\t",array[i]);

printf("\n");

reversal(array,10);

printf("Afterreversal:\n");

for(i=0;i<10;i++)

printf("%d\t",array[i]);

printf("\n");

}

程序运行结果如下:说明:

函数reversal的形式参数p是一个指针变量,用来接收一维数组首元素的地址,在函数中是被当做一维数组使用的。为了提高程序的可读性,可以把它的定义写成一维数组的形式,即该函数的首部可以写成:

voidreversal(intp[],intn)

需要注意的是,p的定义虽然写成了一维数组的形式,但它实际是一个指针变量,所以没有必要定义元素的个数;即使定义了元素的个数,也是没有意义的。主调函数中的调用语句“reversal(array,10)”也可以写成“reversal(&array[0],10)”。

函数调用发生后,被调函数中p所代表的数组和主调函数中array所代表的数组实际上是同一个数组,这就是为什么被调函数中逆置了p数组,而主调函数中的array数组也被逆置了的原因。

读者可以思考一下,把上面程序中main函数中的调用语句改成“reversal(array+3,5)”,可不可以?如果可以,则程序的运行结果是什么?

7.3二维数组

7.3.1二维数组的定义和初始化

数组是用来解决大批量同类型数据的存储和处理问题的。有时候要处理的一批数据在逻辑上是分组的,例如在前面提到的成绩统计问题中,假如要处理的不是一门课的成绩,而是五门课程的成绩,也就是说共有225个成绩需要处理。这些成绩数据,可以按照课程来分组,共5组,每组45个;也可以按照学生来分组,共45组,每组5个。当然,也可以把这225个成绩看做是5行45列或45行5列的矩阵。对于逻辑上有这种结构的数据,直接使用一维数组存储处理起来不是非常方便。C语言中提供了二维数组,可以很方便的存储和处理类似这种结构的数据。二维数组的定义形式如下:

数据类型数组名[行数][列数];

例如如下语句:

inta[3][4];

该语句定义了一个二维数组a,共有12个存储单元(元素),被逻辑地分成3行4列,每个存储单元(元素)可以存放一个int型的数据。二维数组中的每个存储单元(元素)是用两个编号来确定的,借用行列式的术语,把这两个编号分别称为行编号和列编号。与一维数组相同,编号都是从0开始的。

上面定义的二位数组的逻辑结构和物理结构如图7-1所示。图7-1二维数组的逻辑结构和物理结构定义二维数组的同时,可以对其进行初始化,也就是给二维数组的元素赋值。初始化的形式既可以是分行的,也可以是不分行的,例如下面的程序片段:

inta[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};

floatb[2][5]={0.1,1.2,2.3,3.4,4.5,5.6,6.7,7.8,8.9,9.0};

以上程序中,对二维数组a的初始化是分行的,而对二维数组b的初始化是不分行的。不分行初始化是按照二维数组元素在内存中的排列次序,依次把给定初值赋给数组元素。初始化的效果如图7-2所示。图7-2二维数组的初始化对二维数组初始化时,可以进行部分初始化,也就是给出二维数组中的部分元素的初始值,在这种情况下,没有给定初始值的数组元素被编译系统自动初始化为0,例如以下的程序片段:

inta[3][4]={{1,2},{5}};

floatb[2][5]={0.1,1.2,2.3};

按照以上初始化形式,对于数组a,元素a[0][0]、a[0][1]和a[1][0]被分别初始化为1、2和5,其他的元素被初始化为0;对于数组b,元素b[0][0]、b[0][1]和b[0][2]被分别初始化为0.1、1.2和2.3,其他元素被初始化为0。在对二维数组初始化时,可以省略行数的定义,这时候由编译系统根据初始化的形式自动确定二维数组的行数,例如以下的程序片段:

inta[][4]={{1,2},{5},{9}};

floatb[][5]={0.1,1.2,2.3,3.4,4.5,5.6,6.7};

对以上的初始化,编译系统会自动确定数组a的行数为3,数组b的行数为2。需要注意的是,定义二维数组时,列数的定义在任何情况下都是不能省略的。7.3.2二维数组元素的引用

二维数组元素的引用类似于一维数组元素的引用,不同的是引用二维数组元素时,需要指定行编号和列编号(行下标和列下标),引用的形式为:

数组名[行编号][列编号]

下面通过一个例子来说明二维数组在程序中的应用。

例7-1

编写一个程序,功能是输入5个学生的成绩,每个学生有3门功课的成绩,计算每个学生的平均成绩。

对于这个问题,首先考虑的是如何在程序中存储这些成绩。显然,可以利用一个5行3列的二维数组来存放成绩,在这个二维数组中,每行对应一个学生,每列对应一门课程。计算每个学生的平均成绩,就是计算这个二维数组中每一行的平均值。根据这个思路编写出如下源程序:/*源程序7-9*/

#include<stdio.h>

main()

{

floatscore[5][3],sum,avg;

inti,j;

for(i=0;i<5;i++){

printf("请输入第%d个学生的成绩:",i+1);

for(j=0;j<3;j++)

scanf("%f",&score[i][j]);}

for(i=0;i<5;i++){

sum=0;

for(j=0;j<3;j++)

sum=sum+score[i][j];

avg=sum/3;

printf("第%d个学生的平均成绩为:%f\n",i+1,avg);

}

}程序运行结果如下:

二维数组特别适合处理数学中有关行列式的问题。

例7-2

编写程序计算如下两个行列式的乘积:

  

把第一个行列式命名为a,把第二个行列式命名为b,把乘积行列式命名为c。根据行列式乘法运算的定义,c是一个3行5列的行列式,其中:

在程序中定义了三个二维数组,分别存放行列式a、b和c。使用循环,逐一计算乘积行列式每一个分量的值,编写源程序如下:×1≤i≤3,1≤j≤5/*源程序7-10*/

#include<stdio.h>

main()

{

inta[3][4]={

{1,2,3,4},

{5,6,7,8},

{9,10,11,12},};

intb[4][5]={

{20,19,18,17,16},

{15,14,13,12,11},

{10,9,8,7,6},

{5,4,3,2,1}

};

intc[3][5];

inti,j,k;

for(i=0;i<3;i++) for(j=0;j<5;j++){

c[i][j]=0;

for(k=0;k<4;k++)

c[i][j]=c[i][j]+a[i][k]*b[k][j];

}

printf("Matrixc:\n");

for(i=0;i<3;i++){

for(j=0;j<5;j++)

printf("%d\t",c[i][j]);

printf("\n");

}

}程序运行结果如下:

7.4函数间二维数组的传递

7.4.1二维数组元素的地址表示法

C语言中的二维数组,可以看做是由一维数组作为元素构成的一维数组,例如有如下定义:

inta[3][5];

以上语句,定义a是一个3行5列的二维数组。把这个二维数组的每一行看做是一个整体,也就是看做是一个元素,那么它就是一个有3个元素的一维数组。这个一维数组的每一个元素,都是一个有5个元素的一维数组。如果把数组a看做一维数组,它就是由a[0]、a[1]和a[2]三个元素组成的,那么自然就有表达式“a”等价于表达式“&a[0]”(因为一维数组名的值是一维数组首元素的地址)。表达式“&a[0]”代表的是数组中第一行的地址,这个地址加1还是一个地址,自然就是数组中第二行的地址了,即表达式“&a[0]+1”等价于表达式“&a[1]”。推广一下,就有表达式“&a[0]+i”等价于表达式“&a[i]”(0≤i≤2),表达式“a+i”等价于表达式“&a[i]”。表达式“a[i]”代表的是什么呢?就是数组中行号为i的这一行,也就是一个一维数组,它的5个元素是a[i][0]、a[i][1]、…、a[i][4]。因此,就有表达式“a[i]”等价于“&a[i][0]”,表达式“a[i]+j”等价于表达式“&a[i][j]”(0≤i≤2,0≤j≤4)。综合以上结论,可以有如下推导过程:

∵a+i&a[i]

∴*(a+i)*&a[i]a[i]&a[i][0](0≤i≤2)

∴*(a+i)+j&a[i][0]+j&a[i][j](0≤j≤4)

∴*(*(a+i)+j)a[i][j]

这样,在程序中访问二维数组a的元素,就有如下三种形式:a[i][j]、*(a[i]+j)、*(*(a+i)+j)。在这三种形式中,表达式“*(*(a+i)+j)”是本质形式,表达式“a[i][j]”是简略形式,表达式“*(a[i]+j)”是两者之间的一种过渡形式。7.4.2利用行指针变量访问二维数组元素

继续前面的例子,对于如下定义的二维数组:

inta[3][5];

表达式“a”代表的是首行的地址,即“&a[0]”,那么可不可以把这个地址存放在一个指针变量当中呢?如果可以,这个指针变量该如何定义呢?来看下面的定义语句:

int(*pa)[5];在这个语句中定义了一个变量pa,“*”指定了它是一个指针变量,这个指针变量是用来存放连续的5个int型数据的地址的。可以把连续的5个整数看做是一个一维数组,也可以看做是某个二维数组中的一行,所以这个指针变量是一个指向一维数组的指针变量,或者说是一个行指针变量。表达式“a”的值恰好是连续的5个整数的地址,所以可以有如下赋值:

pa=a;

经过以上赋值,就有:

*(*(pa+i)+j)

*(*(a+i)+j)

a[i][j]结合前面讨论过的“*(地址+i)”可以简写成“地址[i]”的形式,表达式“*(*(pa+i)+j)”可以简写成“*(pa[i]+j)”,进一步简写成“pa[i][j]”。也就是说,行指针变量pa可以当作二维数组名使用。

行指针变量在声明时要注意括号的应用,例如把变量pa的定义写成如下形式:

int*pa[5];

因为“[]”的优先级高于“*”,所以pa就被定义为一个有5个元素的数组了,这个数组中存放的是int型数组的地址。这时候,pa就不是一个行指针变量,而是一个指针数组。另外,对行指针变量赋值时必须赋予合适的地址,例如有如下语句:

pa=&a[0][0];

这个语句就是错误的,因为表达式“&a[0][0]”的值是“1个int数据的地址”,和变量pa的类型(5个int型数据的地址)是不同的,所以这个赋值从逻辑和语法上来说都是错误的。7.4.3函数之间二维数组的传递

在函数之间传递二维数组,只需要传递二维数组首行的地址。此时,主调函数的实参是二维数组名,而与之对应的被调函数的形参应该是行指针变量。同时,主调函数还需要向被调函数传递二维数组的行数。下面看一个程序的例子。

例7-3

把方阵的行和列交换。例如一个5阶方阵行和列交换前后如图7-3所示。图7-35阶方阵的行列互换源程序如下:

/*源程序7-11*/

#include<stdio.h>

voidinverseMatrix(int(*pa)[10],intn)

{

inti,j,temp;

for(i=1;i<n;i++)

for(j=0;j<i;j++){

temp=pa[i][j];

pa[i][j]=pa[j][i];

pa[j][i]=temp;

}}

voidoutputMatrix(int(*pa)[10],intn)

{

inti,j;

for(i=0;i<n;i++){

for(j=0;j<n;j++)

printf("%d\t",pa[i][j]);

printf("\n");

}

}

main()

{

inta[10][10]={

{1,2,3,4,5},

{6,7,8,9,10},

{11,12,13,14,15},

{16,17,18,19,20},

{21,22,23,24,25}

};

printf("Beforeinversing:\n");

outputMatrix(a,5);

inverseMatrix(a,5);

printf("Afterinversing:\n");

outputMatrix(a,5);

}程序运行结果如下:

习题

1.编写函数fun,函数原型为:intfun(intscore[],intm,intbelow[])。它的功能是:m个人的成绩存放在score数组中,将低于平均分的人数作为函数值返回,将低于平均分的分数放在below所指的数组中。例如,当score数组中的数据为10、20、30、40、50、60、

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论