第 6章 数 组
6.1 一维数组
6.2 二维数组
6.3 字符数组与字符串
6.4 数组作为函数参数
6.5 程序举例
6.1 一维数组
6.1.1 一维数组的定义与引用
定义一维数组的一般形式如下:
类型说明符 数组名 [常量表达式 ];
其中类型说明符是定义数组中各元素的数据类型, 常量
表达式是说明数组的大小 ( 即数组中元素的个数 。
数组的说明与变量的说明一样, 其作用是为数组分配存
储空间 。
关于数组的说明要注意以下几个问题:
( 1) 数组名的命名规则与变量名相同 。
( 2) 说明数组大小的常量表达式必须为整型, 并且用方括
号括起来 ( 不能用圆括号 ) 。
( 3)说明数组大小的常量表达式中可以包含符号常量,但
不能是变量。
例 6.1 下面的程序说明了如何对数组定义和引用数组元素:
#include "stdio.h"
#define N 5
main()
{ int i,a[N];
for (i= 0; i< N; i= i+ 1) a[i]= i;
for (i= 0; i< N; i= i+ 1)
printf("%5d",a[i]);
printf("\n");
}
在这个程序中,首先定义了一个长度为 5的整型
一维数组 a,然后利用 for循环对其中的每一个元素
( a[0]~ a[4])进行赋值,最后利用 for循环输出这 5
个元素值。
在 C语言中,凡是一般简单变量可以使用的地
方都可以使用数组元素。
6.1.2 一维数组的初始化
在 C语言中, 给数组元素提供数据的方法有以下 3种 。
( 1) 利用赋值语句逐个对数组中的元素进行赋值 。
( 2) 利用输入函数逐个输入数组中的各个元素 。 例如,
#include "stdio.h"
main()
{ int i,a[5];
for (i= 0; i< 5; i= i+ 1) scanf("%d",&a[i]);
}
其中 &a[i]表示取数组元素 a[i]的地址 。
( 3)初始化。
下面对静态一维数组的初始化作三点说明:
( 1)可以只给数组的前若干个元素赋初值,此时后面的元素
均将自动赋以初值 0。
( 2)在对全部元素赋初值时,说明语句中可以不指定数组长
度,其长度默认为与初值表中数据的个数相同。
( 3)虽然标准 C语言规定只能对, 静态存储, 的数组进行初
始化,即除了可以对外部 (全局 )数组进行初始化外,还可以对
用 static说明的局部数组进行初始化。
例 6.3 分析下列程序的输出结果:
#include "stdio.h"
main()
{ int k,x[5];
static int y[5];
int z[5]= {0,0,0};
for (k= 0; k< 5; k++ )
{ printf("%5d%5d%5d",x[k],y[k],z[k]);
printf("\n");
}
}
6.2 二维数组
6.2.1 二维数组的定义与引用
定义二维数组的一般形式如下:
类型说明符 数组名 [常量表达式 1][常量表达式 2];
6.2.2 二维数组的初始化
与一维数组一样,也可以对静态存储的二维数组进行初始
化。
在对二维数组进行初始化时要注意以下几点。
( 1)在分行给二维数组赋初值时,对于每一行都可以
只对前几个元素赋初值,后面未赋初值的元素系统将自动赋
初值 0;并且,还可以只对前几行元素赋初值。
( 2)在给全部元素赋初值时,说明语句中可以省略第
一维的长度说明。
( 3)在分行赋初值时,也可以省略第一维的长度说明。
6.3 字符数组与字符串
6.3.1 字符数组的定义与初始化
定义字符数组的一般形式如下:
char 数组名 [常量表达式 ]; 一维字符数组
char 数组名 [常量表达式 1][常量表达式 2]; 二维字符数组
( 1) 当对字符数组中所有元素赋初值时, 数组的长度说
明可以省略 。
( 2)可以只对前若干元素赋初值。
( 3)虽然标准 C语言规定只能对, 静态存储, 的字符数组
进行初始化,即除了可以对外部 (全局 )字符数组进行初始化外,
还可以对用 static说明的局部字符数组进行初始化。
6.3.2 字符串
C语言规定,字符串常量(简称字符串)要用一对双
撇号括起来。在一个字符串常量中,最后还包括一个结
束符 ‘ \0’。
C语言允许用字符串常量对字符数组进行初始化 。
6.3.3 字符数组与字符串的输入与输出
1.输入输出一个字符 (格式说明符为 %c)
在用于输入时,输入项为数组元素地址。在具体输
入时,各字符之间不要分隔,字符也不要用单撇号括起
来。
在用于输出时,输出项为数组元素。
2.输入输出一个字符串(格式说明符为 %s)
在用格式说明符 %s进行输入输出时,其输入输出项
均为数组名。但在输入时,相邻两个字符串之间要用空
格分隔,系统将自动地在字符串最后加结束符 '\0'。
6.3.4 字符串处理函数
下面简单介绍一些常用的字符串处理函数 。
( 1) puts( 字符数组名 )
功能:输出一个字符串到终端 。
( 2) gets( 字符数组名 )
功能:从终端输入一个字符串到字符数组, 并返回字符数组
的地址 。
( 3) strcat( 字符数组 1,字符串 2)
功能:将字符串 2连接到字符串 1的后面, 并返回字符串 1的地
址 。
( 4) strcpy(字符数组 1,字符串 2)
功能:字符串 2拷贝到字符数组 1中。
( 5) strcmp( 字符串 1,字符串 2)
功能:比较字符串 。
这个函数的返回值如下:
若字符串 1=字符串 2,则返回值为 0;
若字符串 1>字符串 2,则返回值为正整数;
若字符串 1<字符串 2,则返回值为负整数 。
( 6) strlen( 字符串 )
功能:测试字符串长度 。
( 7) 大小写转换函数
大小写转换函数有以下两个:
strlwr( 字符串 ) 将字符串中大写字母转换成小写字母 。
strupr( 字符串 ) 将字符串中小写字母转换成大写字母 。
6.4 数组作为函数参数
6.4.1 形参数组与实参数组的结合
例 6.8 用选择法对无序序列进行排序 。
图 6.1 选择法排序流程图
select(b, n)
f o r i =0 t o n – 2
k =I
f o r j =i+1 t o n – 1
b [ j ] < b [ k ]
k =j
k ≠ i
b [ i ] ? b [ k ]
结束返回
y es no
no y es
C程序如下:
/* select.c */
select(b,n)
int n,b[];
{ int i,j,k,d;
for (i= 0; i<= n- 2; i= i+ 1)
{ k= i;
for (j= i+ 1; j<= n- 1; j= j+ 1)
if (b[j]<b[k]) k= j;
if (k!= i) {d= b[i]; b[i]= b[k]; b[k]= d; }
}
}
/* ex.c */
#include "stdio.h"
#include "select.c"
main()
{ int k;
static int s[10]= {3,5,4,1,9,6,10,56,34,12};
printf("\n");
for (k= 0; k<10; k= k+ 1) printf("%4d",s[k]));
printf("\n");
select(s,10);
for (k= 0; k<10; k= k+ 1) printf("%4d",s[k]));
printf("\n");
}
在 C语言中, 形参数组与实参数组之间的结合要注意以下几
点:
( 1)调用函数与被调用函数中分别定义数组,其数组名可以
不同,但类型必须一致。
( 2)在 C语言中,形参变量与实参之间的结合是采用数值结
合的,因此,如果在被调用函数中改变了形参的值,是不会改
变实参值的。
( 3)实参数组与形参数组的大小可以一致也可以不一致,C
编译系统对形参数组的大小不作检查,调用时只将实参数组的
首地址传给形参数组。
( 4) 虽然函数中的形参数组一般不指定大小, 但为了控制形
参数组的使用范围, 一般要在函数中另设一个传送形参数组元
素个数的形参变量, 如函数 select()中的形参 n。
6.4.2 二维数组作为函数参数
二维数组作为函数参数与一维数组完全类似 。
例 6.9 利用函数求两个矩阵的乘积矩阵 。
在例 6.4中说明了两个矩阵相乘的方法 。 但在例 6.4中, 只
能对固定的两个矩阵进行相乘, 没有通用性 。 在本例中, 用
函数 matmul()来实现矩阵相乘, 在主函数 main()中再用具体
的矩阵来调用它 。
具体的 C程序如下:
#include "stdio.h"
main()
{ int i,j,c[2][3];
static int a[2][4]= {1,2,3,4,5,6,7,8};
static int b[4][3]= {1,2,3,4,5,6,7,8,9,10,11,12};
matmul(a,b,c,2,4,3);
for (i= 0; i< 2; i= i+ 1)
{ for (j= 0; j< 3; j= j+ 1)
printf("%5d",c[i][j]);
printf("\n");
}
printf("\n");
}
matmul(a,b,c,m,n,k)
int m,n,k,a[2][4],b[4][3],c[2][3];
{ int i,j,t;
for (i= 0; i< m; i= i+ 1)
for (j= 0; j< k; j= j+ 1)
{ c[i][j]= 0;
for (t= 0; t< n; t= t+ 1)
c[i][j]= c[i][j]+ a[i][t]*b[t][j];
}
return;
}
6.5 程序举例
例 6.10 从键盘输入年, 月, 日, 计算并输出该日是该年
的第几天 。
C程序如下:
#include "stdio.h"
main()
{ int year,month,day,k,sum;
static int t[]= {31,0,31,30,31,30,31,31,30,31,30,31};
printf("input year,month,day:");
scanf("%d,%d,%d",&year,&month,&day);
if ((year%4== 0 && year%100!= 0)||year%400== 0)
t[1]= 29;
else t[1]= 28;
sum= day;
for (k= 0; k< month- 1; k= k+ 1)
sum= sum+ t[k];
printf("Dyas= %d\n",sum);
}
例 6.12 编写一个对长度为 n的线性表进行冒泡排序的
函数 。
冒泡排序的过程如下:
从前到后扫描待排序序列, 依次比较相邻两个项目
的大小, 若发现逆序就进行交换, 最后使最大者换到序
列的最后;然后从后到前扫描剩下的序列, 依次比较相
邻两个项目的大小, 若发现逆序就进行交换, 最后使最
小者换到序列的最前面 。 对剩下的序列重复这个过程,
直到剩下的序列为空为止 。
C函数如下:
void prbub(p,n)
int n; double p[];
{ int m,k,j,i;
double d;
k= 0; m= n- 1;
while (k< m=
{ j= m- 1; m= 0;
for (i= k; i<= j; i++ )
if (p[i]> p[i+ 1])
{ d= p[i]; p[i]= p[i+ 1]; p[i+ 1]= d; m= i; }
j= k+ 1; k= 0;
for (i= m; i>= j; i-- )
if (p[i- 1]> p[i])
{ d= p[i]; p[i]= p[i- 1]; p[i- 1]= d; k= i; }
}
return;
}