第九章 数组前面所用到的数据为基本类型 (整,实,字符 ),
为了丰富数据类型,须提供强有力的数据表达方式 。 C语言提供了一种构造类型数据 –––由基本类型按某一规则组合在一起 。
其中 数组 是 C语言中最简单的构造类型:同一种 (基本 )类型按一定顺序组合在一起的数据类型。
数组中几个重要概念
※ C语言数据类型分为:
( 1) 基本类型 ( 整形,字符型,浮点型 )
( 2) 组合类型组合类型,数组类型,结构体类型,共用体类型 。
※ 数组定义:是指一组同类型数据组成的序列 。
※ 数组表示方法:
( 1) 用一个统一的数组名称来标识这一组数据;
int age[3]; age
( 2) 用下标来指示数组中元素的序号 。
例 age[0],age[1],age[2]
注意,同一数组中的所有元素必须属于同一数据类型 。
TC IDE
§ 9.1 一维数组定义和数组元素引用
9.1.1 一维数组的定义
1,数组名的确定方法同变量名。
2,C语言用方括号 [ ]表示数组元素个数。
形式,类型说明符 数组名 [常量表达式 ];
例,int a [20];
float x [100];
3,常量表达式为常量或符号常量。不允许有变量,
其表达式的值代表了元素的个数。
例,int a[20];
表示有 20个元素且元素从 0开始编排,a[0],a[1]…,a [19]
4,可在定义时对数组赋初值,方法如下,
对部分元素赋初值
int a[10]={0,1,2,3,4};
对全部元素赋初值
int a[10]={10,11,12,13,14,15,16,17,18,19};
前 5个元素初值分别为 0,1,2,3,4,后 5个元素初值为 0。
若赋全部元素的初值,可省略常量表达式
int a[ ]={0,1,2,3};
表示 a[4],即只有 4个元素。
9.1.2 一维数组的引用
2,引用方式,数组名 [下标 ]
代表了一个元素,等价一个同类型的变量。
3,一维数组各元素分配在连续地内存单元之中。
1,须象使用变量那样,数组要先定义,后使用
C编译不检查下标是否“越界”。
例,a [0]?5+a[1]? 6 为正确的算术表达式
9.1.5 一维数组的应用
用循环 for实现,
for (i=2; i<20; i++)
f [i]=f [i –2]+f [i –1];
例,求 Fibonacci 数列。
定义数组,并赋初值
int f [20]={1,1};
注意,下标越界问题,i =2且 i<20
打印,每 5个数换一行。
for (i=0; i<20; i++)
{ if (i%5= =0) printf(" \n ");
printf (" %12d ",f [i]);
}
程序如下:
main ( )
{ int i;
int f [20]={1,1};
for (i=2; i<20; i++)
f [i]=f [i–2]+f [i–1];
for (i=0; i<20; i++)
{
if (i%5 = =0) printf("\n");
printf("%12d",f [i] );}
}
1
8
89
987
5
55
610
6765
运行结果如下:
1
13
144
1597
2
21
133
1584
3
34
377
4181
例 2,排序问题 –––计算机处理数据的一个重要问题排序算法较多,一种最简单的算法 –––选择排序法 用得较多。基本思路,设有 n个数,需将它们从小到大顺序排列。则:
2,在剩下的 n –1个元素中,找出第二小的元素并把它放在第二个位置上。
3,对上述过程重复,直至剩下一个元素。
1,从 n个元素中,通过比较,找出最小元素,放在第一个位置上。
例,8,4,20,100,28,1,
两次交换第 2次,1,4,20,100,28,8 –––一次交换第 3次,1,4,8,100,28,20 ––– 一次交换第 4次,1,4,8,28,100,20,
1,4,8,20,100,28 两次交换第 5次,1,4,8,20,28,100 –––一次交换第 1次,4,8,20,100,28,1
1,8,20,100,28,4
从以上例子可以看到,用到两种循环,第一种循环 ––找第 i小 的元素,第二种循环 ––对其后的元素的一一比较。
流程图,
初始化输入 n个元素?a数组
i?1
j?i+1
a[i]>a[j]
交换 a[i]
a[j]
B
A
No
Yes
j?j+1
j>n
i?i+1
i> n–1
打印结果结束内循环外循环
B
A
No
Yes
Yes
No
程序,main ( )
{ int a [11];
int i,j,t;
printf (" please input 10 n~:\n ");
for (i=1; i<=10; i++)
scanf(" %d ",&a[i]);
printf(" \n ");
for (i=1; i<=9; i++)
for (j=i+1; j<=10; j++)
if (a[i]>a[j])
{ t=a[i]; a[i]=a[j]; a[j]=t;}
printf (" the sorted numbers,\n ");
for (i=1; i<=10; i++)
printf(" %d ",a[i]);
}
另一种排序法:冒泡排序法
9.2 一维数组和指针
9,2.1、一维数组的指针表示方法:
1、数组的地址确定,( 例,a[10] )
( 1)起始地址:数组名 a,是一个指针常量
( 2)数组中的元素的地址:
a[0]的地址也即数组地址,a
a[1]的地址可用 a+1表示
…… a[i] 的地址可用 a+i 表示注意,a+i表示 a[i]的地址,即 a+i指向 a数组中下标为 i的元素。
2、数组元素的引用方法:
( 1) 下 标法 ;
例,a[3];
( 2)地址法:
通过给出地址访问某个元素。
例,通过 a+3就能找到 a[3],即,*( a+3)就是 a[3];
( 3)指针变量法:
使指针变量直接指向某一数组元素,通过该指针就可访问它所指向的元素。
例,假设使 p指向了 a[3],那么通过 p就 能找到 a[3],
即,*p就是 a[3];
TC IDE
9.2 一维数组和指针
9.2.1、一维数组的指针表示方法:
3、应当注意的几个问题:
( 1)引用数组元素的效率不同
a、使用下标法引用数组元素:
先计算出数组元素的地址( a+i),然后 再找到它指向的存储单元,读入或写入它的值。
b、用指针变量 p指向数组元素:
不必每次计算数组元素地址。
( 2)使用指针法访问数组元素时,也要注意“下标是否越界”

( 3) 使用指向数组元素的指针变量时,要特别注意指针变量当前值。
例,p=a;
for(i=0;i<5;i++)
scanf(“%d”,p++);
TC IDE
9.2 一维数组和指针
1、一维数组指针表示总结:
( 1)一维数组名代表了该数组的起始地址,即该数组第一个元素的地址;它是一个指向所代表的数组即指向其起始单元的指针。
( 2)一维数组的任何一个元素的地址,都可以用其数组名加上一个偏移量(其单位为数组元素的个数)来表示。
例 a == &a[0] a[0] == *a
a+1 == &a[1] a[1] == *(a+1)
a+i == &a[i] a[i] == *(a+i)
TC IDE
§ 9.3 数组作为函数参数分为两种情况,
1,数组元素作为实参
2,数组名同时为形、实参一、数组元素作为实参由于数组元素与相同类型的简单变量地位完全一样;因此,数组元素作函数参数也和简单变量一样,也是 值的单向传递
int x,a[10];
如,x?a[5]即 a[5]为一元素,与 x完全一样。
将数组元素作为参数:
( 1) 和变量作为参数的用法相同;
( 2) 这种传送方式仍然是,值传送,方式,即只能从实参传给形参,而不能从形参传给实参 。
例:
ave=fun (a[0],a[1],a[2]) ;

float fun(float a,float b,float c) {
float sum; aver;
sum=a+b+c; aver=sum/3.0; return (aver);}
TC IDE
例,设有两个同样大小的一维数组,a[10],b[10]将相应元素比较,统计 a数组元素 大于 b数组 对应元素的个数,小于的个数,相等的个数。
程序如下:
main ( )
{
int a[10],b[10],i,n=0,m=0,k=0;
printf("enter array a:\n");
for (i=0; i<10; i++)
scanf (“%d",&a[i]);
printf ("\n");
printf("enter array b:\n");
for (i=0; i<10; i++)
scanf ("%d",&b[i]);
printf ("\n");
for (i=0; i<10; i++)
{ if (large (a[i],b[i])= =1) n=n+1;
else if (large (a[i],b[i])= =0) m=m+1;
else k=k+1;}
printf ("a[i]>b[i] %d times\na[i]=b[i] %d
times\na[i]<b[i] %d times\n",n,m,k);
if (n>k) printf("array a is larger than array b\n");
else if (n<k) printf("array a is smaller than array b\n");
else printf("array a is equal to array b\n");
}
int large(int x,int y)
{ int flag;
if (x>y) flag=1;
else if (x<y) flag= –1;
else flag=0;
return (flag);
}
运行情况如下:
enter array a:
1 3 5 7 9 8 6 4 2 0?
enter array b:
5 3 8 9 –1 –3 5 6 0 4?
a[i]>b[i] 4 times
a[i]=b[i] 1 times
a[i]<b[i] 5 times
array a is smaller than array b
特点,直接用数组名作参数时,则为地址传送 (不是值传送 ),即实参数组的首地址传递给形参数组首地址。所以,实参、形参数组共享相同的内存单元。
1,形参数组可不指定大小,也可用另一参数作大小,
以确定使用实参数组的元素个数。
2,形参、实参数组必须类型一致。
3,多维数组方式一样,仅第一维大小的说明可省略二、数组名作实、形参将数组名作为函数参数,
注意,( 1) 实参数组和形参数组应分别在它们所在的函数中定义;
( 2)当以数组名作参数时,采取的不是“值传送”方式,而是“地址传送”方式。
( 3)以数组名作参数时,实参数组必须定义为具有确定长度的数组,而形参数组可以不定义长度。
TC IDE
例 1,有一个一维数组 score,内放 10个学生成绩,
求平均成绩。
float average (float array[10])
{ int i;
float aver,sum=array [0];
for (i=1; i<10; i++)
sum=sum+array[i];
aver=sum/10;
程序如下:
return( aver);
}
main ( )
{ float score [10],aver;
int i;
printf("input 10 score:\n");
for (i=0;i<10; i++)
scanf ("%f",&score[i]);
printf("\n");
aver=average(score);
printf(" average score is %5.2f ",aver);
}
运行情况如下:
input 10 scores:
100 56 78 98.5 76 87 99 67.5 75 97?
average score is 83.40
程序 2,
float average (float array[ ],int n)
{int i;
float aver,sum=array[0];
for (i=1; i<n; i++)
sum=sum+array[i];
aver=sum/n;
return (aver);
}
main( )
{ static float score_1[5]={98.5,97,91.5,60,55}
static float score _2 [10]={67.5,89.5,99,69.5,77,
89.5,76.5,54,60,99.5}
printf (“the average of class A is %6.2f\n”,average
(score_1,5));
printf (“the average of class B is %6.2f\n”,average
(score_2,10));
}
运行结果如下:
the average of class A is 80.40
the average of class B is 78.20
§ 9.5 二维数组
9.5.1 二维数组的定义
1,不可将定义写为 int a[4,10]。
形式 类型说明符 数组名 [常量表达式 ] [常量表达式 ]
例,int a[4] [10];
float x[8] [20];
2,可将二维数组的元素看成为若干个特殊的一维数组。
如,int b[3] [4];
则,有三个特殊的一维数组 b[0],b[1],b[2],每一个又有四个元素,
b[0][0],b[0][1],b[0][2],b[0][3],
b[1][0],b[1][1],b[1][2],b[1][3],
b[2][0],b[2][1],b[2][2],b[2][3]
3,二维数组的存放方式为,按行存放。由此可推广至三维,n维数组的定义和存放。
即,最右边的下标变化最快。
4,初始化,
按行给二维数组赋初值,
int a[3][4]={{1,2,3,4},{5,6,7,8},
{9,10,11,12}};
可以去掉内部的 { }。
可以对部分元素赋初值,但需表达清楚。如,
int a[3][4]={{1,2},{3},{8}}。
则相当于 1 2 0 0
3 0 0 0
8 0 0 0
可通过赋初值决定数组大小。如为二维,则只可省略第一维的大小,
int a[ ][4]={1,2,3,…,12};
9.5.2 二维数组元素的引用形式,数组名 [下标 ][下标 ]
其中的下标为整型表达式,但不得越界。
与一维数组元素一样,二维数组元素相当于同类型的简单变量。
9.5.3 程序举例
a=
1 2 3
4 5 6 b=
1 4
2 5
3 6
程序如下,main ( )
{
int a[2] [3]={{1,2,3},{4,5,6}};
int b[3] [2],i,j;
例 1 将一个二维数组行和列元素互换,存到另一个二维数组中。例如:
printf("array a,\n");
for (i=0; i<=1; i++)
{for (j=0; j<=2; j++)
{printf("%5d",a[i][j]);
b[j][i]=a[i][j];
}
printf("\n");
}
printf("array b:\n");
for (i=0; i<=2; i++)
{
for (j=0; j<=1; j++)
printf("%5d",b[i][j]);
printf("\n");
}
}
运行结果如下:
array a:
1 2 3
4 5 6
array b:
1 4
2 5
3 6
数组元素数据的输入必须以循环方式进行或者定义时置初值。
例 2,有一个 3× 4的矩阵,要求编程序求出其中值最大的那个元素的值,以及所在的行号和列号。
先用 N- S流程图表示算法,
max= a[0][0]
for i=0 to 2
for j=0 to 3
a[i][j]>max
max= a[i][j]
row=i
colum=j
输出,max和 row,colum
真 假
二维数组一般用二重循环据此写出以下程序:
main ( )
{ int i,j,row=0,colum=0,max;
int a[3][4]={{1,2,3,4},{9,8,7,6},{–10,10,–5,2}};
max=a[0][0];
for (i=0;i<=2; i++)
for (j=0; j<=3; j++)
if (a[i][j]>max)
{max=a[i][j];
row=i;
colum=j;
}
printf( "max=%d,row=%d,colum=%d\n ",max,row,
colum);
}
输出结果为:
max=10,row=2,colum=1