,C语言程序设计,
课程讲义
第 6章 数组
2006年 4月
上一章节课程回顾
1、四种循环语句,goto to 语句; While
语句 ; for 语句; do while 语句。这三
条为当型循环,后一条为直到型循环。
2、介绍了两条循环的辅助语句,break;
continue语句,一条是中断循环的执行,
另一条则是结束循环的本次运行。
3、介绍了循环的嵌套以及循环控制程序的
应用举例
迄今为止,我们使用的都是属于基本类型
(整型、字符型、实型)的数据,c语言还提供
了构造类型的数据,它们有:数组类型、结构
体类型、共用体类型,构造类型数据是由基本
类型数据按一定规则组成的,因此有的书称它
们为“导出类型”。
本章只介绍数组。数组是有序数据的集合。
数组中的每一个元素都属于同一个数据类型。
用一个统一的数组名和下标来唯一地确定数组
中的元素,有关数组的概念和其它高级语言中
介绍的是相同的,不再赘述。本章只介绍 C语言
中如何定义和使用数组。
本章概述,
6.1 一维数组的定义和引用
6.2 二维数组的定义和引用
6.3 字符数组
6.4 程序举例
6.5 本章小结
本章主要内容
6.1.2 一维数组的定义方式
6.1.3 一维数组元素的引用
6.1.4 一维数组的初始化
6.1.5 一维数组程序举例
6.1 一维数组的定义和引用
6.1.1 数组的概念
构造类型数据,数组、结构体、共用体。
数组,有序数据的集合,整体参加运算。
例,a1x1+a2x2+a3x3+… +anxn
其中,a1 a2 a3…… an 是一组有序的数,称为数组
数组中成员分量 ai称为 数组元素,
数组元素的类型称为该数组的 基类型 。
第 i个
数组元素
C中数组元素的表示,用带下标的变量,a[i]
数组名
下标
6.1.1数组的概念
例如,a1x1+a2x2+a3x3+… +anxn
定义为,int a[8];float b[10];
表示 a数组可以使用 8个元素,a[0]~ a[7]
数据类型 数组名 [常量表达式 ];
例如 int a[ 10] ;
数组体积,数组中所包含的元素的个数。
数组体积=第 1维大小
数组的定义 实例,
int try[10];
char string[100];
整型常量
6.1.2一维数组的定义方式
类型说明符是任一种基本数据类型或构造数据类型。
数组名是用户定义的数组标识符。
方括号中的常量表达式表示数据元素的个数,也称为数组的
长度 。
例如,
int a[10]; 说明整型数组 a,有 10个元素。
float b[10],c[20]; 说明实型数组 b,有 10个元素,实型
数组 c,有 20个元素。
char ch[20]; 说明字符数组 ch,有 20个元素。
对于数组类型说明应注意以下几点,
? 数组的类型实际上是指数组元素的取值类型。对于同一个
数组,其所有元素的数据类型都是相同的。
? 数组名的书写规则应符合标识符的书写规定。
? 数组名不能与其它变量名相同。
几点说明
? 数组说明中常见的错误
① float a[0]; /* 数组大小为 0没有意义 */
② int b(2)(3); /* 不能使用圆括号 */
③ int k,a[k]; /* 不能用变量说明数组 */
④ int n;
scanf (“%d”,&n);
int a[n]; /* 数组说明必须在可执行语句前 */
?但数组说明中可以包括符号常量,如:若有定义
#define N 10
int arry[N];
float average[N]
① 数组元素是组成数组的基本单元。数组
元素也是一种变量,其标识方法为数组
名后跟一个下标。下标表示了元素在数
组中的顺序号。
② 数组元素的引用一般形式为,
数组名 [下标 ]
int i,a[20];
for (i=0;i<20;i++) a[i]=i*i;
for (i=0;i<20;i++) printf(,%d”,a[i]);
例 1
6.1.3一维数组元素的引用
输入 /输出数组,int x[10];
for (k=0; k<10; k++)
scanf (“%d”,&x[k]);
for (k=0; k<=9; ++k)
printf (“%d\n”,x[k]);
输出数组
函数被调用 10次
读数组
函数被调用 10次 例 2
③ 对于 非字符 数组,只能 对数组中的 元素 进
行访问,不能 进行 整体 操作。
数组必须先定义,然后使用。 C语言规定只能
逐个引用数组元素而不能一次引用整个数组。
错误,scanf (“%d%d%d%d%d%d%d%d%d%d”,x);
scanf (“%d”,x);
printf(“%d”,x);
printf(“%d%d%d%d%d%d%d%d%d%d”,x);
④ 对于 字符 数组,可以按 元素 访问,也可以进
行 整体 访问。
如有定义,int a[10];
如有定义,char string[80];
例,scanf(“%s”,string);
printf(“%s”,string);
【 例 6.1】
main()
{
int i,a[10];
for(i=0;i<=9;i++)
a[i]=i;
for(i=9;i>=0;i--)
printf("%d ",a[i]);
}
【 例 6.2】
main()
{
int i,a[10];
for(i=0;i<10;)
a[i++]=i;
for(i=9;i>=0;i--)
printf("%d",a[I ]);
}
【 例 6.3】
main()
{
chara[10],c=?A?;
int i;
for(i=0;i<10;)
a[i++]=c++;
for(i=0;i<=9;i++)
printf("%d ",a[i]);
printf("\n%sn",a );}
单个元素的引用
对数组元素
的整体访问
一维数组在内存中顺序存放
数组在内存中的存放
x[0]
x[1]
x[2]
x[3]
低地址
高地址
例,int x[4];
讨论
float x[4];
double x[4];
long x[4];
各占多少个字节
X数组占 8个字节
6.1.4一维数组的初始化
数组初始化赋值是指在数组定义时给数组元素赋予初值。数
组初始化是在编译阶段进行的。这样将减少运行时间,提高
效率。
初始化赋值的一般形式为,
类型说明符 数组名 [常量表达式 ]={值,值 …… 值 };
三种为数组提供数据的方法,
static int a[6]= {1,2,3,4,5,6};
static float b[10]= {1.1,2.0,3.8};
static double c[ ]= {1.0,2.1,3.2,4.5};
例 3 根据数据定义数组长度
初始化部分元素
静态存储类型初值为 0
main( ) main( )
{ static int a[5],i; { int a[5],i;
for(i=0;i<=4;i++) for(i=0;i<=4;i++)
printf(“%d,,a[i]); printf(“%d”,a[i]);
} }
输出, 输出,
0 0 0 0 0 五个无规则数
只有静态存储和外部存储数组 在定义时可直接 初始化
main()
{int k,a[]={0,0,0,0,0,0,0,0,0,0};
float fs;
scanf(,%f”,fs);
if (fs==100) k=9;
else
k=(int)(fs/10);
a[k]=a[k]+1;
printf(“%d%d%d%d%d”,a[9],a[8],a[7],a[6],?);
}
统计分数
位置应是,
a[5]+a[4]+a[3]+a[2]+a[1]+a[0]
定义数组并初始化
数组元素引用
分类计数器
6.1.5一维数组程序举例
例 【 6.4】
main()
{
int i,max,a[10];
printf("input 10 numbers:\n");
for(i=0;i<10;i++)
scanf("%d",&a[i]);
max=a[0];
for(i=1;i<10;i++)
if(a[i]>max) max=a[i];
printf("maxmum=%d\n",max);
}
例 【 6.5】
本例程序中第一个 for语句逐个输入 10个数到数组 a中。 然后
把 a[0]送入 max中。在第二个 for语句中,从 a[1]到 a[9]逐个与
max中的内容比较,若比 max的值大,则把该下标变量送入
max中,因此 max总是在已比较过的下标变量中为最大者。比
较结束,输出 max的值。
【 例 6.6】
main()
{ int i,j,p,q,s,a[10];
printf("\n input 10 numbers:\n");
for(i=0;i<10;i++)
scanf("%d",&a[i]);
for(i=0;i<10;i++){
p=i;q=a[i];
for(j=i+1;j<10;j++)
if(q<a[j]) { p=j;q=a[j]; }
if(i!=p)
{s=a[i];
a[i]=a[p];
a[p]=s; }
printf("%d",a[i]);
} }
本例程序中用了两个并列的 for循环语句,在第二
个 for 语句中又嵌套了一个循环语句。 第一个 f r语句
用于输入 10个
元素的初值 第二个 for语句
用于排序
本程序的排序采用逐个比较的
方法进行。在 i次循环时,把第
一个元素的下标 i赋于 p,而把
该下标变量值 a[i]赋于 q
然后进入小循环,从
a[i+1]起到最后一个元
素止逐个与 a[i]作比较,
有比 a[i]大者则将其下
标送 p,元素值送 q。 一次循环结束后,p即为最大元素的下标,q则为该元素值。若此时
i≠p,说明 p,q值均已不是进入小循
环之前所赋之值,则交换 a[i]和 a[p]
之值。 此时 a[i]为已排序完毕的元
素。输出该值之后转入下一次循环。
对 i+1以后各个元素排序。
6.2 二维数组的定义和引用
6.2.1二维数组的定义
6.2.2二维数组元素的引用
6.2.3二维数组的初始化
6.2.4二维数组程序举例
一,格式,类型说明符 数组名 [常量 e1][常量 e2];
例如 a数组,
a11x11 a12x22 a13x13
a21x21 a22x22 a23x23
a31x31 a32x32 a33x33
a41x41 a42x42 a43x43
三维数组 b[3][4][5]表示,共有 3× 4× 5= 60个元素。
b[0][0][0]~ b[2][3][4]
定义为,int a[4][3],b[3][4][5];
表示 a数组可以使用 4× 3个元素,a[0][0]~ a[3][2]
6.2.1二维数组的定义
最大行下标
最
大
列
下
标
二、二维数组的存储
?二维数组按行存放
?三维数组按页存放
例如,int b[2][2]
b[0][0]
b[0][1]
b[1][0]
b[1][1]
低地址
高地址
b数组占 8个字节
多维数组的存储顺序是,
第一维的下标变化最慢
第一行元素
第二行元素
讨论
double[10][10][6]
有多少元素?
占多少字节?
10?10?6=600个元素
600?8=4800个字节
硬件存储器却是连续编址的,也就是说存储器单元是按一
维线性排列的。在C语言中,二维数组是按行排列的。
memory
a[0][0]
a[0][2]
a[1][1]
a[1][0]
a[2][0]
a[2][1]
a[0][1]
a[1][2]
a[2][2]
a[3][0]
a[3][1]
a[3][2]
a[3]
a[2]
a[1]
a[0]
a
?二 维数组的每一行
可看作一个 一维数组
一维数组名
例如,int a[4][3]
一维数组名
先存放 a[0]行,再存放 a[1]行,最后存放 a[3]行。每行中有
四个元素也是依次存放。由于数组 a说明为 int类型,该类型
占两个字节的内存空间,所以每个元素均占有两个字节 )。
按存储顺序截取数据
缺少初值
补零 第一行无初值 缺省时按实际
数据确定行
static int a[3][3]= {{1,2,3},{4,5,6},{7,8,9}};
static int a[3][3]= {1,2,3,4,5,6,7,8,9};
static int a[3][3]= {{1,2},{4},{7,0,9}};
static int a[3][3]= {{ },{4,0}};
static int a[ ][3]= {1,2,3,4,5,6,7,8,9};
二维数组初始化也是在类型说明时给各下标变
量赋以初值。二维数组可按行分段赋值,也可
按行连续赋值
6.2.3二维数组的初始化
初始化与赋值的区别,
数组初始化, 源程序进行 编译 时为数组元素
分配存储单元并给定初值 。
main( )
{ int a[2];
a[0]=1; a[1]=2;
……
}
main( )
{ static int a[2] ={ 1,2};
……
}
数组元素赋值, 程序 执行 过程中执行赋值语句。
数组是一种构造类型的数据。二维数组可以看作是由一维
数组的嵌套而构成的。设一维数组的每个元素都又是一
个数组,就组成了二维数组。当然,前提是各元素类型
必须相同。根据这样的分析,一个二维数组也可以分解
为多个一维数组。C语言允许这种分解。
如二维数组 a[3][4],可 分解为三个一维数组,其数组名分
别为,
a[0]
a[1]
a[2]
对这三个一维数组不需另作说明即可使用。这三个一维数
组都有 4个元素,例如:一维数组 a[0]的元素为
a[0][0],a[0][1],a[0][2],a[0][3]。
必须强调的是,a[0],a[1],a[2]不能当作下标变量使用,它
们是数组名,不是一个单纯的下标变量。
例:用数组来求 Fibonacci数列问题(前 20项)
1 1 2 3 5
8 13 21 34 55
89 144 233 377 610
987 1597 2584 4181 6765
已知, f [0] = 1,f [1] = 1;
求解,f [i] = f [i-1] + f [i-2] ( i ? 2 )
数列前两个数为 1,1,其它值为前两项之和。
算法如下,
[例 6.7]
main( )
{ int i ;
static int f [20] = { 1,1 };
/ * 数组初始化 f [0] = 1; f [1] = 1; */
for ( i=2; i<20; i++)
f [i] = f [i-2] + f [i-1];
/ *按数列的算法为 f [2] ~ f[19]赋值 ( 当 i ?2 ) */
/*输出各元素值 */
for ( i =0; i<20; i++ )
{ if ( i %5= = 0 ) printf( \n” ) ; / * 每 5 个数据换一
行显示 * /
printf (,%12d”,f [i] ) ;}
}
6.2.4二维数组程序举例
[例 6.8]将一个二维数组行和列元素互换,存到另一个
二维数组中。例如,
1 2 3 1 4
a=( ) b=( 2 5 )
4 5 6 3 6
程序如下,
main()
{
static int a[2][3]={{1,2,3},{4,5,6}};
static int b[3][2],i,j;
printf("array a,\n");
for(i=0;i<=1;i++) /*行控制 */
{for(j=0;j<=2;j++) /*列 控制 */
{printf("%5d",a[i][j]); /*输出 a数组 */
b[j][i]=a[i][j]; } /*行 列交换 */
printf("\n");}
printf("array b,\n");
for(i=0; i<=2; i++) /*b数组 */
{for(j= 0; j<=1; j++)
printf("%5d",b[i][j]); /*输出 b数组 */
printf("\n");
} }
运行结果如右,
array a,
1 2 3
4 5 6
array b,
1 4
2 5
3 6
6.3 字符数组
6.3.1字符数组的定义
6.3.2字符数组的初始化
6.3.3字符数组的引用
6.3.4字符串和字符串结束标志
6.3.5字符数组的输入输出
6.3.6字符串处理函数
复习,字符型数据
字符常量,’ a’,’ A’,’ \’开头的字符序
列
例,’ \n’表示换行 ; ’ \r’表示回车;
字符串常量,用双引号括起来的字符序列 。
例,, Ch”,” 123”等 。 长度 不 限, 末尾加 ’ \0’
字符变量,存放字符常量的变量, 用 char说明 。
符号常量,以指定符号代表其后的, 一串字
符,
格式,#define 标识符 常量
可以是任意
类型常量
字符数据的输入输出
?格式化输入输出函数,
scanf(),printf(),”%c”
? 使用库函数,
getchar(),putchar(ch)
#include,stdio.h”
输入输出 一个 字符的两种方法,从键盘上
读一个字符
输出到屏幕
一个字符
6.3.1字符数组的定义
用来存放字符量的数组称为字符数组。
例如,char c[10];
由于字符型和整型通用,也可以定义为 int c[10]
但这时每个数组元素占 2个字节的内存单元。
字符数组也可以是二维或多维数组。
例如,char c[5][10];
即为二维字符数组。
格式,类型说明符 数组名 [维数说明 ];
? 一 维字符型数组作为一个 字符串变量 使用。
? 二 维字符型数组相当于一个 字符串数组,每行存放
一个字符串。
字符数组也允许在定义时作初始化赋值。
例如,
char c[10]={?c?,? ?,?p?,?r?,?o?,?g?,?r?,?a?};
赋值后各元素的值为,
数组 C c[0]的值为‘ c? c[1]的值为‘ ’
c[2]的值为‘ p? c[3]的值为‘ r?
c[4]的值为‘ 0? c[5]的值为‘ g?
c[6]的值为‘ r? c[7]的值为‘ a?
其中 c[8]未赋值,因此系统自动赋予 c[8]为 0值。
当对全体元素赋初值时也可以省去长度说明。
例如,
char c[]={`c`,` `,`p`,`r`,`o`,`g`,`r`,`a`,`m`};
这时 C数组的长度自动定为 9。
6.3.2字符数组的初始化
按存储顺序截取字符
后边补 3个
空字符 \0
字符型数组的初始化 示例
第一维下标由引号确定
取长度为 7
static char a[7]= {?W?,?i?,?n?,?d?,?o?,?w?,?s?};
static char a[ ]= {?W?,?i?,?n?,?d?,?o?,?w?,?s?};
static char a[7]= {??D?,?o?,?s?,? ?};
static char b[20]= {”How do you do?”};
static char c[ ]=, How do you do?”;
字符串
字符串组
加串结束标志 \0
static char l[3][7]= {”BASIC”,”Pascal”,”C”};
static char l[ ][7]= {”BASIC”,”Pascal”,”C”};
【 例 6.9】
main()
{
int i,j;
char a[][5]={{'B','A','S','I','C',},{'d','B','A','S','E'}};
for(i=0;i<=1;i++)
{
for(j=0;j<=4;j++)
printf("%c",a[i][j]);
printf("\n");
}
}
6.3.3字符数组的引用
在C语言中没有专门的字符串变量,通常用一个字符数组来
存放一个字符串。前面介绍字符串常量时,已说明字符串总
是以 '\0'作为串的结束符。因此当把一个字符串存入一个数
组时,也把结束符 '\0'存入数组,并以此作为该字符串是否
结束的标志。有了 '\0'标志后,就不必再用字符数组的长度
来判断字符串的长度了。
6.3.4字符串和字符串结束标志
C语言允许用字符串的方式对数组作初始化赋值。
例如,
char c[]={'c',' ','p','r','o','g','r','a','m'};
可写为,
char c[]={"C program"};
或去掉 { }写为,
char c[]="C program";
用字符串方式赋值比用字符逐个赋值要多占一个
字节,用于存放字符串结束标志 '\0'。上面的数组
c在内存中的实际存放情况为,
C program\0 ?\0'是由 C编译系统自动加上的。
由于采用了 ‘ \0'标志,所以在用字符串赋初值时
一般无须指定数组的长度,而由系统自行处理。
C p r o g r a m \0
在采用字符串方式后,字符数组的输入输出将变得简单方便。
除了上述用字符串赋初值的办法外,还可用 printf函数和
scanf函数一次性输出输入一个字符数组中的字符串,而不必
使用循环语句逐个地输入输出每个字符。
6.3.5字符数组的输入输出
【 例 6.10】
main()
{
char []="BASIC\ndBASE";
printf("%s\n",c);
}
【 例 7.11】
main()
{
char st[15];
printf("input
string:\n");
scanf("%s",st);
printf("%s\n",st);
}
本例的 printf函数
中,使用的格式字
符串为,%s”,表
示输出的是一个字
符串
本例中由于定义数组长
度为 15,因此输入的
字符串长度必须小于
15,以留出一个字节
用于存放字符串结束标
志 `\0`。
应该说明的是,对一个字符数组,如果不作初始化赋值,则
必须说明数组长度。还应该特别注意的是,当用 scanf函数
输入字符串时,字符串中不能含有空格,否则将以空格作为
串的结束符。
例如当输入的字符串中含有空格时,运行情况为,
input string,//输入提示串
this is a book //从键盘输入的字符串
输出为,this
从输出结果可以看出空格以后的字符都未能输出。为了避免
这种情况,可多设几个字符数组分段存放含空格的串。
程序可改写如下,
【 例 6.12】
main()
{
char st1[6],st2[6],st3[6],st4[6];
printf("input string:\n");
scanf("%s%s%s%s",st1,st2,st3,st4);
printf("%s %s %s %s\n",st1,st2,st3,st4);
}
本程序分别设了四个数组,输
入的一行字符的空格分段分别装
入四个数组。然后分别输出这四
个数组中的字符串。
scanf的各输入项必须以地址方式出现,如 &a,&b等。但在
前例中却是以数组名方式出现的,这是为什么呢?
这是由于在C语言中规定,数组名就代表了该数组的首地址。
整个数组是以首地址开头的一块连续的内存单元。
如有字符数组 char c[10],在内存可表示如图。
C[0] C[1] C[2] C[3] C[4] C[5] C[6] C[7] C[8] C[9]
设数组 c的首地址为 2000,也就是说 c[0]单元地址为
2000。则数组名 c就代表这个首地址。因此在 c前面
不能再加地址运算符 &。如写作 scanf("%s",&c);则
是错误的。在执行函数 printf("%s",c) 时,按数组
名 c找到首地址,然后逐个输出数组中各个字符直到
遇到字符串终止标志 '\0'为止。
C语言提供了丰富的字符串处理函数,大致可分为字符串
的输入、输出、合并、修改、比较、转换、复制、搜索几类。
使用这些函数可大大减轻编程的负担。用于输入输出的字符
串函数,在使用前应包含头文件 "stdio.h",使用其它字符
串函数则应包含头文件 "string.h"。
6.3.6字符串处理函数
1、字符串输出函数 puts
格式,puts (字符数组名 )
功能:把字符数组中的字符串输出到显示器。 即在屏
幕上显示该字符串。
#include"stdio.h"
main()
{ char c[]="BASIC\ndBASE";
puts(c);
}
2、字符串输入函数 gets
格式,gets (字符数组名 )
功能:从标准输入设备键盘上输入一个字符串。
本函数得到一个函数值,即为该字符数组的首地址。
【 例 6.13】
#include"stdio.h"
main()
{
char st[15];
printf("input
string:\n");
gets(st);
puts(st);
}
可以看出当输入的字
符串中含有空格时,
输出仍为全部字符串。
说明 gets函数并不以
空格作为字符串输入
结束的标志,而只以
回车作为输入结束。
这是与 scanf函数不
同的。
3、字符串连接函数 strcat
格式,strcat (字符数组名 1,字符数组名 2)
功能:把字符数组 2中的字符串连接到字符数组
1 中字符串的后面,并删去字符串 1后的串标志
,\0”。本函数返回值是字符数组 1的首地址。
【 例 6.14】
#include"string.h"
main()
{
static char st1[30]="My name is ";
int st2[10];
printf("input your name:\n");
gets(st2);
strcat(st1,st2);
puts(st1);
}
本程序把初始化赋值的
字符数组与动态赋值的
字符串连接起来。要注
意的是,字符数组 1应
定义足够的长度,否则
不能全部装入被连接的
字符串。
4、字符串拷贝函数 strcpy
格式,strcpy (字符数组名 1,字符数组名 2)
功能:把字符数组 2中的字符串拷贝到字符数
组 1中。串结束标志,\0”也一同拷贝。字符数
名 2,也可以是一个字符串常量。这时相当于把
一个字符串赋予一个字符数组。
【 例 6.15】
#include"string.h"
main()
{
char st1[15],st2[]="C Language";
strcpy(st1,st2);
puts(st1);printf("\n");
}
本函数要求字
符数组 1应有足
够的长度,否
则不能全部装
入所拷
贝的字符串。
5、字符串比较函数 strcmp
格式,strcmp(字符数组名 1,字符数组名 2)
功能:按照 ASCII码顺序比较两个数组中的字符串,
并由函数返回值返回比较结果。
字符串 1=字符串 2,返回值= 0;
字符串 2〉 字符串 2,返回值 〉 0;
字符串 1〈 字符串 2,返回值 〈 0。
本函数也可用于比较两个字符串常量,或比较数组和字符
串常量 。
【 例 6.16】
#include"string.h"
main()
{ int k;
static char st1[15],st2[]="C Language";
printf("input a string:\n");
gets(st1);
k=strcmp(st1,st2);
if(k==0) printf("st1=st2\n");
if(k>0) printf("st1>st2\n");
if(k<0) printf("st1<st2\n");
}
本程序中把输入的字符串和数
组 st2中的串比较,比较结果
返回到 k中,根据 k值再输出结
果提示串。当输入为 dbase时,
由 ASCII 码可知,dBASE”大
于,C Language”故 k〉 0,输
出结果,st1>st2”。
6、测字符串长度函数 strlen
格式,strlen(字符数组名 )
功能:测字符串的实际长度 (不含字符串结束标
志‘ \0?) 并作为函数返回值。
【 例 6.17】
#include"string.h"
main()
{ int k;
static char st[]="C language";
k=strlen(st);
printf("The lenth of the string
is %d\n",k);
}
【 例 6.18】 把一个整数按大小顺序插入已排好序的数组中。
为了把一个数按大小插入已排好序的数组中,应首先确定排
序是从大到小还是从小到大进行的。设排序是从大到小进序
的,则可把欲插入的数与数组中各数逐个比较,当找到第一
个比插入数小的元素 i时,该元素之前即为插入位置。然后从
数组最后一个元素开始到该元素为止,逐个后移一个单元。
最后把插入数赋予元素 i即可。如果被插入数比所有的元素值
都小则插入最后位置。
本程序首先对数组 a中的 10个数从大到小排序并输出排序结
果。然后输入要插入的整数 n。再用一个 for语句把 n和数组
元素逐个比较,如果发现有 n>a[i]时,则由一个内循环把 i以
下各元素值顺次后移一个单元。后移应从后向前进行 (从 a[9]
开始到 a[i]为止 )。后移结束跳出外循环。插入点为 i,把 n赋
予 a[i]即可。 如所有的元素均大于被插入数,则并未进行过
后移工作。此时 i=10,结果是把 n赋于 a[10]。最后一个循环
输出插入数后的数组各元素值。
6.4 程序举例
main()
{
int
i,j,p,q,s,n,a[11]={127,3,6,
28,54,68,87,105,162,18};
for(i=0;i<10;i++)
{ p=i;q=a[i];
for(j=i+1;j<10;j++)
if(q<a[j])
{p=j;q=a[j];}
if(p!=i)
{
s=a[i];
a[i]=a[p];
a[p]=s;
}
printf("%d ",a[i]);
}
printf("\ninput number:\n");
scanf("%d",&n);
for(i=0;i<10;i++)
if(n>a[i])
{for(s=9;s>=i;s--)
a[s+1]=a[s];
break;}
a[i]=n;
for(i=0;i<=10;i++)
printf("%d ",a[i]);
printf("\n");
}
【 例 6.19】 在二维数组 a中选出各行最大的元素
组成一个一维数组 b。
a=( 3 16 87 65
4 32 11 108
10 25 12 37)
b=(87 108 37)
本题的编程思路是,在数组 A的每一行中寻找最大的元素,
找到之后把该值赋予数组 B相应的元素即可。程序如下,
main()
{
int a[][4]={3,16,87,65,4,32,11,108,10,25,12,27};
int b[3],i,j,l;
for(i=0;i<=2;i++)
{ l=a[i][0];
for(j=1;j<=3;j++)
if(a[i][j]>l) l=a[i][j];
b[i]=l;}
printf("\narray a:\n");
for(i=0;i<=2;i++)
{ for(j=0;j<=3;j++)
printf("%5d",a[i][j]);
printf("\n");}
printf("\narray b:\n");
for(i=0;i<=2;i++)
printf("%5d",b[i]);
printf("\n");
}
程序中第一个 for语句中
又嵌套了一个 for语句组
成了双重循环。外循环
控制逐行处理,并把每
行的第 0列元素赋予 l。
进入内循环后,把 l与后面
各列元素比较,并把比 l大
者赋予 l。
内循环结束时 l 即为该行最
大的元素,然后把 l值赋予
b[i]。等外循环全部完成时,
数组 b中已装入了 a各行中
的最大值。
6.5 本章小结
1.数组是程序设计中最常用的数据结构。数组可
分为数值数组 (整数组,实数组 ),字符数组以及
后面将要介绍的指针数组,结构数组等。
2.数组可以是一维的,二维的或多维的。
3.数组类型说明由类型说明符、数组名、数组长
度 (数组元素个数 )三部分组成。数组元素又称为
下标变量。数组的类型是指下标变量取值的类型。
4.对数组的赋值可以用数组初始化赋值,输入函
数动态赋值和赋值语句赋值三种方法实现。对数
值数组不能用赋值语句整体赋值、输入或输出,
而必须用循环语句逐个对数组元素进行操作。
课程讲义
第 6章 数组
2006年 4月
上一章节课程回顾
1、四种循环语句,goto to 语句; While
语句 ; for 语句; do while 语句。这三
条为当型循环,后一条为直到型循环。
2、介绍了两条循环的辅助语句,break;
continue语句,一条是中断循环的执行,
另一条则是结束循环的本次运行。
3、介绍了循环的嵌套以及循环控制程序的
应用举例
迄今为止,我们使用的都是属于基本类型
(整型、字符型、实型)的数据,c语言还提供
了构造类型的数据,它们有:数组类型、结构
体类型、共用体类型,构造类型数据是由基本
类型数据按一定规则组成的,因此有的书称它
们为“导出类型”。
本章只介绍数组。数组是有序数据的集合。
数组中的每一个元素都属于同一个数据类型。
用一个统一的数组名和下标来唯一地确定数组
中的元素,有关数组的概念和其它高级语言中
介绍的是相同的,不再赘述。本章只介绍 C语言
中如何定义和使用数组。
本章概述,
6.1 一维数组的定义和引用
6.2 二维数组的定义和引用
6.3 字符数组
6.4 程序举例
6.5 本章小结
本章主要内容
6.1.2 一维数组的定义方式
6.1.3 一维数组元素的引用
6.1.4 一维数组的初始化
6.1.5 一维数组程序举例
6.1 一维数组的定义和引用
6.1.1 数组的概念
构造类型数据,数组、结构体、共用体。
数组,有序数据的集合,整体参加运算。
例,a1x1+a2x2+a3x3+… +anxn
其中,a1 a2 a3…… an 是一组有序的数,称为数组
数组中成员分量 ai称为 数组元素,
数组元素的类型称为该数组的 基类型 。
第 i个
数组元素
C中数组元素的表示,用带下标的变量,a[i]
数组名
下标
6.1.1数组的概念
例如,a1x1+a2x2+a3x3+… +anxn
定义为,int a[8];float b[10];
表示 a数组可以使用 8个元素,a[0]~ a[7]
数据类型 数组名 [常量表达式 ];
例如 int a[ 10] ;
数组体积,数组中所包含的元素的个数。
数组体积=第 1维大小
数组的定义 实例,
int try[10];
char string[100];
整型常量
6.1.2一维数组的定义方式
类型说明符是任一种基本数据类型或构造数据类型。
数组名是用户定义的数组标识符。
方括号中的常量表达式表示数据元素的个数,也称为数组的
长度 。
例如,
int a[10]; 说明整型数组 a,有 10个元素。
float b[10],c[20]; 说明实型数组 b,有 10个元素,实型
数组 c,有 20个元素。
char ch[20]; 说明字符数组 ch,有 20个元素。
对于数组类型说明应注意以下几点,
? 数组的类型实际上是指数组元素的取值类型。对于同一个
数组,其所有元素的数据类型都是相同的。
? 数组名的书写规则应符合标识符的书写规定。
? 数组名不能与其它变量名相同。
几点说明
? 数组说明中常见的错误
① float a[0]; /* 数组大小为 0没有意义 */
② int b(2)(3); /* 不能使用圆括号 */
③ int k,a[k]; /* 不能用变量说明数组 */
④ int n;
scanf (“%d”,&n);
int a[n]; /* 数组说明必须在可执行语句前 */
?但数组说明中可以包括符号常量,如:若有定义
#define N 10
int arry[N];
float average[N]
① 数组元素是组成数组的基本单元。数组
元素也是一种变量,其标识方法为数组
名后跟一个下标。下标表示了元素在数
组中的顺序号。
② 数组元素的引用一般形式为,
数组名 [下标 ]
int i,a[20];
for (i=0;i<20;i++) a[i]=i*i;
for (i=0;i<20;i++) printf(,%d”,a[i]);
例 1
6.1.3一维数组元素的引用
输入 /输出数组,int x[10];
for (k=0; k<10; k++)
scanf (“%d”,&x[k]);
for (k=0; k<=9; ++k)
printf (“%d\n”,x[k]);
输出数组
函数被调用 10次
读数组
函数被调用 10次 例 2
③ 对于 非字符 数组,只能 对数组中的 元素 进
行访问,不能 进行 整体 操作。
数组必须先定义,然后使用。 C语言规定只能
逐个引用数组元素而不能一次引用整个数组。
错误,scanf (“%d%d%d%d%d%d%d%d%d%d”,x);
scanf (“%d”,x);
printf(“%d”,x);
printf(“%d%d%d%d%d%d%d%d%d%d”,x);
④ 对于 字符 数组,可以按 元素 访问,也可以进
行 整体 访问。
如有定义,int a[10];
如有定义,char string[80];
例,scanf(“%s”,string);
printf(“%s”,string);
【 例 6.1】
main()
{
int i,a[10];
for(i=0;i<=9;i++)
a[i]=i;
for(i=9;i>=0;i--)
printf("%d ",a[i]);
}
【 例 6.2】
main()
{
int i,a[10];
for(i=0;i<10;)
a[i++]=i;
for(i=9;i>=0;i--)
printf("%d",a[I ]);
}
【 例 6.3】
main()
{
chara[10],c=?A?;
int i;
for(i=0;i<10;)
a[i++]=c++;
for(i=0;i<=9;i++)
printf("%d ",a[i]);
printf("\n%sn",a );}
单个元素的引用
对数组元素
的整体访问
一维数组在内存中顺序存放
数组在内存中的存放
x[0]
x[1]
x[2]
x[3]
低地址
高地址
例,int x[4];
讨论
float x[4];
double x[4];
long x[4];
各占多少个字节
X数组占 8个字节
6.1.4一维数组的初始化
数组初始化赋值是指在数组定义时给数组元素赋予初值。数
组初始化是在编译阶段进行的。这样将减少运行时间,提高
效率。
初始化赋值的一般形式为,
类型说明符 数组名 [常量表达式 ]={值,值 …… 值 };
三种为数组提供数据的方法,
static int a[6]= {1,2,3,4,5,6};
static float b[10]= {1.1,2.0,3.8};
static double c[ ]= {1.0,2.1,3.2,4.5};
例 3 根据数据定义数组长度
初始化部分元素
静态存储类型初值为 0
main( ) main( )
{ static int a[5],i; { int a[5],i;
for(i=0;i<=4;i++) for(i=0;i<=4;i++)
printf(“%d,,a[i]); printf(“%d”,a[i]);
} }
输出, 输出,
0 0 0 0 0 五个无规则数
只有静态存储和外部存储数组 在定义时可直接 初始化
main()
{int k,a[]={0,0,0,0,0,0,0,0,0,0};
float fs;
scanf(,%f”,fs);
if (fs==100) k=9;
else
k=(int)(fs/10);
a[k]=a[k]+1;
printf(“%d%d%d%d%d”,a[9],a[8],a[7],a[6],?);
}
统计分数
位置应是,
a[5]+a[4]+a[3]+a[2]+a[1]+a[0]
定义数组并初始化
数组元素引用
分类计数器
6.1.5一维数组程序举例
例 【 6.4】
main()
{
int i,max,a[10];
printf("input 10 numbers:\n");
for(i=0;i<10;i++)
scanf("%d",&a[i]);
max=a[0];
for(i=1;i<10;i++)
if(a[i]>max) max=a[i];
printf("maxmum=%d\n",max);
}
例 【 6.5】
本例程序中第一个 for语句逐个输入 10个数到数组 a中。 然后
把 a[0]送入 max中。在第二个 for语句中,从 a[1]到 a[9]逐个与
max中的内容比较,若比 max的值大,则把该下标变量送入
max中,因此 max总是在已比较过的下标变量中为最大者。比
较结束,输出 max的值。
【 例 6.6】
main()
{ int i,j,p,q,s,a[10];
printf("\n input 10 numbers:\n");
for(i=0;i<10;i++)
scanf("%d",&a[i]);
for(i=0;i<10;i++){
p=i;q=a[i];
for(j=i+1;j<10;j++)
if(q<a[j]) { p=j;q=a[j]; }
if(i!=p)
{s=a[i];
a[i]=a[p];
a[p]=s; }
printf("%d",a[i]);
} }
本例程序中用了两个并列的 for循环语句,在第二
个 for 语句中又嵌套了一个循环语句。 第一个 f r语句
用于输入 10个
元素的初值 第二个 for语句
用于排序
本程序的排序采用逐个比较的
方法进行。在 i次循环时,把第
一个元素的下标 i赋于 p,而把
该下标变量值 a[i]赋于 q
然后进入小循环,从
a[i+1]起到最后一个元
素止逐个与 a[i]作比较,
有比 a[i]大者则将其下
标送 p,元素值送 q。 一次循环结束后,p即为最大元素的下标,q则为该元素值。若此时
i≠p,说明 p,q值均已不是进入小循
环之前所赋之值,则交换 a[i]和 a[p]
之值。 此时 a[i]为已排序完毕的元
素。输出该值之后转入下一次循环。
对 i+1以后各个元素排序。
6.2 二维数组的定义和引用
6.2.1二维数组的定义
6.2.2二维数组元素的引用
6.2.3二维数组的初始化
6.2.4二维数组程序举例
一,格式,类型说明符 数组名 [常量 e1][常量 e2];
例如 a数组,
a11x11 a12x22 a13x13
a21x21 a22x22 a23x23
a31x31 a32x32 a33x33
a41x41 a42x42 a43x43
三维数组 b[3][4][5]表示,共有 3× 4× 5= 60个元素。
b[0][0][0]~ b[2][3][4]
定义为,int a[4][3],b[3][4][5];
表示 a数组可以使用 4× 3个元素,a[0][0]~ a[3][2]
6.2.1二维数组的定义
最大行下标
最
大
列
下
标
二、二维数组的存储
?二维数组按行存放
?三维数组按页存放
例如,int b[2][2]
b[0][0]
b[0][1]
b[1][0]
b[1][1]
低地址
高地址
b数组占 8个字节
多维数组的存储顺序是,
第一维的下标变化最慢
第一行元素
第二行元素
讨论
double[10][10][6]
有多少元素?
占多少字节?
10?10?6=600个元素
600?8=4800个字节
硬件存储器却是连续编址的,也就是说存储器单元是按一
维线性排列的。在C语言中,二维数组是按行排列的。
memory
a[0][0]
a[0][2]
a[1][1]
a[1][0]
a[2][0]
a[2][1]
a[0][1]
a[1][2]
a[2][2]
a[3][0]
a[3][1]
a[3][2]
a[3]
a[2]
a[1]
a[0]
a
?二 维数组的每一行
可看作一个 一维数组
一维数组名
例如,int a[4][3]
一维数组名
先存放 a[0]行,再存放 a[1]行,最后存放 a[3]行。每行中有
四个元素也是依次存放。由于数组 a说明为 int类型,该类型
占两个字节的内存空间,所以每个元素均占有两个字节 )。
按存储顺序截取数据
缺少初值
补零 第一行无初值 缺省时按实际
数据确定行
static int a[3][3]= {{1,2,3},{4,5,6},{7,8,9}};
static int a[3][3]= {1,2,3,4,5,6,7,8,9};
static int a[3][3]= {{1,2},{4},{7,0,9}};
static int a[3][3]= {{ },{4,0}};
static int a[ ][3]= {1,2,3,4,5,6,7,8,9};
二维数组初始化也是在类型说明时给各下标变
量赋以初值。二维数组可按行分段赋值,也可
按行连续赋值
6.2.3二维数组的初始化
初始化与赋值的区别,
数组初始化, 源程序进行 编译 时为数组元素
分配存储单元并给定初值 。
main( )
{ int a[2];
a[0]=1; a[1]=2;
……
}
main( )
{ static int a[2] ={ 1,2};
……
}
数组元素赋值, 程序 执行 过程中执行赋值语句。
数组是一种构造类型的数据。二维数组可以看作是由一维
数组的嵌套而构成的。设一维数组的每个元素都又是一
个数组,就组成了二维数组。当然,前提是各元素类型
必须相同。根据这样的分析,一个二维数组也可以分解
为多个一维数组。C语言允许这种分解。
如二维数组 a[3][4],可 分解为三个一维数组,其数组名分
别为,
a[0]
a[1]
a[2]
对这三个一维数组不需另作说明即可使用。这三个一维数
组都有 4个元素,例如:一维数组 a[0]的元素为
a[0][0],a[0][1],a[0][2],a[0][3]。
必须强调的是,a[0],a[1],a[2]不能当作下标变量使用,它
们是数组名,不是一个单纯的下标变量。
例:用数组来求 Fibonacci数列问题(前 20项)
1 1 2 3 5
8 13 21 34 55
89 144 233 377 610
987 1597 2584 4181 6765
已知, f [0] = 1,f [1] = 1;
求解,f [i] = f [i-1] + f [i-2] ( i ? 2 )
数列前两个数为 1,1,其它值为前两项之和。
算法如下,
[例 6.7]
main( )
{ int i ;
static int f [20] = { 1,1 };
/ * 数组初始化 f [0] = 1; f [1] = 1; */
for ( i=2; i<20; i++)
f [i] = f [i-2] + f [i-1];
/ *按数列的算法为 f [2] ~ f[19]赋值 ( 当 i ?2 ) */
/*输出各元素值 */
for ( i =0; i<20; i++ )
{ if ( i %5= = 0 ) printf( \n” ) ; / * 每 5 个数据换一
行显示 * /
printf (,%12d”,f [i] ) ;}
}
6.2.4二维数组程序举例
[例 6.8]将一个二维数组行和列元素互换,存到另一个
二维数组中。例如,
1 2 3 1 4
a=( ) b=( 2 5 )
4 5 6 3 6
程序如下,
main()
{
static int a[2][3]={{1,2,3},{4,5,6}};
static int b[3][2],i,j;
printf("array a,\n");
for(i=0;i<=1;i++) /*行控制 */
{for(j=0;j<=2;j++) /*列 控制 */
{printf("%5d",a[i][j]); /*输出 a数组 */
b[j][i]=a[i][j]; } /*行 列交换 */
printf("\n");}
printf("array b,\n");
for(i=0; i<=2; i++) /*b数组 */
{for(j= 0; j<=1; j++)
printf("%5d",b[i][j]); /*输出 b数组 */
printf("\n");
} }
运行结果如右,
array a,
1 2 3
4 5 6
array b,
1 4
2 5
3 6
6.3 字符数组
6.3.1字符数组的定义
6.3.2字符数组的初始化
6.3.3字符数组的引用
6.3.4字符串和字符串结束标志
6.3.5字符数组的输入输出
6.3.6字符串处理函数
复习,字符型数据
字符常量,’ a’,’ A’,’ \’开头的字符序
列
例,’ \n’表示换行 ; ’ \r’表示回车;
字符串常量,用双引号括起来的字符序列 。
例,, Ch”,” 123”等 。 长度 不 限, 末尾加 ’ \0’
字符变量,存放字符常量的变量, 用 char说明 。
符号常量,以指定符号代表其后的, 一串字
符,
格式,#define 标识符 常量
可以是任意
类型常量
字符数据的输入输出
?格式化输入输出函数,
scanf(),printf(),”%c”
? 使用库函数,
getchar(),putchar(ch)
#include,stdio.h”
输入输出 一个 字符的两种方法,从键盘上
读一个字符
输出到屏幕
一个字符
6.3.1字符数组的定义
用来存放字符量的数组称为字符数组。
例如,char c[10];
由于字符型和整型通用,也可以定义为 int c[10]
但这时每个数组元素占 2个字节的内存单元。
字符数组也可以是二维或多维数组。
例如,char c[5][10];
即为二维字符数组。
格式,类型说明符 数组名 [维数说明 ];
? 一 维字符型数组作为一个 字符串变量 使用。
? 二 维字符型数组相当于一个 字符串数组,每行存放
一个字符串。
字符数组也允许在定义时作初始化赋值。
例如,
char c[10]={?c?,? ?,?p?,?r?,?o?,?g?,?r?,?a?};
赋值后各元素的值为,
数组 C c[0]的值为‘ c? c[1]的值为‘ ’
c[2]的值为‘ p? c[3]的值为‘ r?
c[4]的值为‘ 0? c[5]的值为‘ g?
c[6]的值为‘ r? c[7]的值为‘ a?
其中 c[8]未赋值,因此系统自动赋予 c[8]为 0值。
当对全体元素赋初值时也可以省去长度说明。
例如,
char c[]={`c`,` `,`p`,`r`,`o`,`g`,`r`,`a`,`m`};
这时 C数组的长度自动定为 9。
6.3.2字符数组的初始化
按存储顺序截取字符
后边补 3个
空字符 \0
字符型数组的初始化 示例
第一维下标由引号确定
取长度为 7
static char a[7]= {?W?,?i?,?n?,?d?,?o?,?w?,?s?};
static char a[ ]= {?W?,?i?,?n?,?d?,?o?,?w?,?s?};
static char a[7]= {??D?,?o?,?s?,? ?};
static char b[20]= {”How do you do?”};
static char c[ ]=, How do you do?”;
字符串
字符串组
加串结束标志 \0
static char l[3][7]= {”BASIC”,”Pascal”,”C”};
static char l[ ][7]= {”BASIC”,”Pascal”,”C”};
【 例 6.9】
main()
{
int i,j;
char a[][5]={{'B','A','S','I','C',},{'d','B','A','S','E'}};
for(i=0;i<=1;i++)
{
for(j=0;j<=4;j++)
printf("%c",a[i][j]);
printf("\n");
}
}
6.3.3字符数组的引用
在C语言中没有专门的字符串变量,通常用一个字符数组来
存放一个字符串。前面介绍字符串常量时,已说明字符串总
是以 '\0'作为串的结束符。因此当把一个字符串存入一个数
组时,也把结束符 '\0'存入数组,并以此作为该字符串是否
结束的标志。有了 '\0'标志后,就不必再用字符数组的长度
来判断字符串的长度了。
6.3.4字符串和字符串结束标志
C语言允许用字符串的方式对数组作初始化赋值。
例如,
char c[]={'c',' ','p','r','o','g','r','a','m'};
可写为,
char c[]={"C program"};
或去掉 { }写为,
char c[]="C program";
用字符串方式赋值比用字符逐个赋值要多占一个
字节,用于存放字符串结束标志 '\0'。上面的数组
c在内存中的实际存放情况为,
C program\0 ?\0'是由 C编译系统自动加上的。
由于采用了 ‘ \0'标志,所以在用字符串赋初值时
一般无须指定数组的长度,而由系统自行处理。
C p r o g r a m \0
在采用字符串方式后,字符数组的输入输出将变得简单方便。
除了上述用字符串赋初值的办法外,还可用 printf函数和
scanf函数一次性输出输入一个字符数组中的字符串,而不必
使用循环语句逐个地输入输出每个字符。
6.3.5字符数组的输入输出
【 例 6.10】
main()
{
char []="BASIC\ndBASE";
printf("%s\n",c);
}
【 例 7.11】
main()
{
char st[15];
printf("input
string:\n");
scanf("%s",st);
printf("%s\n",st);
}
本例的 printf函数
中,使用的格式字
符串为,%s”,表
示输出的是一个字
符串
本例中由于定义数组长
度为 15,因此输入的
字符串长度必须小于
15,以留出一个字节
用于存放字符串结束标
志 `\0`。
应该说明的是,对一个字符数组,如果不作初始化赋值,则
必须说明数组长度。还应该特别注意的是,当用 scanf函数
输入字符串时,字符串中不能含有空格,否则将以空格作为
串的结束符。
例如当输入的字符串中含有空格时,运行情况为,
input string,//输入提示串
this is a book //从键盘输入的字符串
输出为,this
从输出结果可以看出空格以后的字符都未能输出。为了避免
这种情况,可多设几个字符数组分段存放含空格的串。
程序可改写如下,
【 例 6.12】
main()
{
char st1[6],st2[6],st3[6],st4[6];
printf("input string:\n");
scanf("%s%s%s%s",st1,st2,st3,st4);
printf("%s %s %s %s\n",st1,st2,st3,st4);
}
本程序分别设了四个数组,输
入的一行字符的空格分段分别装
入四个数组。然后分别输出这四
个数组中的字符串。
scanf的各输入项必须以地址方式出现,如 &a,&b等。但在
前例中却是以数组名方式出现的,这是为什么呢?
这是由于在C语言中规定,数组名就代表了该数组的首地址。
整个数组是以首地址开头的一块连续的内存单元。
如有字符数组 char c[10],在内存可表示如图。
C[0] C[1] C[2] C[3] C[4] C[5] C[6] C[7] C[8] C[9]
设数组 c的首地址为 2000,也就是说 c[0]单元地址为
2000。则数组名 c就代表这个首地址。因此在 c前面
不能再加地址运算符 &。如写作 scanf("%s",&c);则
是错误的。在执行函数 printf("%s",c) 时,按数组
名 c找到首地址,然后逐个输出数组中各个字符直到
遇到字符串终止标志 '\0'为止。
C语言提供了丰富的字符串处理函数,大致可分为字符串
的输入、输出、合并、修改、比较、转换、复制、搜索几类。
使用这些函数可大大减轻编程的负担。用于输入输出的字符
串函数,在使用前应包含头文件 "stdio.h",使用其它字符
串函数则应包含头文件 "string.h"。
6.3.6字符串处理函数
1、字符串输出函数 puts
格式,puts (字符数组名 )
功能:把字符数组中的字符串输出到显示器。 即在屏
幕上显示该字符串。
#include"stdio.h"
main()
{ char c[]="BASIC\ndBASE";
puts(c);
}
2、字符串输入函数 gets
格式,gets (字符数组名 )
功能:从标准输入设备键盘上输入一个字符串。
本函数得到一个函数值,即为该字符数组的首地址。
【 例 6.13】
#include"stdio.h"
main()
{
char st[15];
printf("input
string:\n");
gets(st);
puts(st);
}
可以看出当输入的字
符串中含有空格时,
输出仍为全部字符串。
说明 gets函数并不以
空格作为字符串输入
结束的标志,而只以
回车作为输入结束。
这是与 scanf函数不
同的。
3、字符串连接函数 strcat
格式,strcat (字符数组名 1,字符数组名 2)
功能:把字符数组 2中的字符串连接到字符数组
1 中字符串的后面,并删去字符串 1后的串标志
,\0”。本函数返回值是字符数组 1的首地址。
【 例 6.14】
#include"string.h"
main()
{
static char st1[30]="My name is ";
int st2[10];
printf("input your name:\n");
gets(st2);
strcat(st1,st2);
puts(st1);
}
本程序把初始化赋值的
字符数组与动态赋值的
字符串连接起来。要注
意的是,字符数组 1应
定义足够的长度,否则
不能全部装入被连接的
字符串。
4、字符串拷贝函数 strcpy
格式,strcpy (字符数组名 1,字符数组名 2)
功能:把字符数组 2中的字符串拷贝到字符数
组 1中。串结束标志,\0”也一同拷贝。字符数
名 2,也可以是一个字符串常量。这时相当于把
一个字符串赋予一个字符数组。
【 例 6.15】
#include"string.h"
main()
{
char st1[15],st2[]="C Language";
strcpy(st1,st2);
puts(st1);printf("\n");
}
本函数要求字
符数组 1应有足
够的长度,否
则不能全部装
入所拷
贝的字符串。
5、字符串比较函数 strcmp
格式,strcmp(字符数组名 1,字符数组名 2)
功能:按照 ASCII码顺序比较两个数组中的字符串,
并由函数返回值返回比较结果。
字符串 1=字符串 2,返回值= 0;
字符串 2〉 字符串 2,返回值 〉 0;
字符串 1〈 字符串 2,返回值 〈 0。
本函数也可用于比较两个字符串常量,或比较数组和字符
串常量 。
【 例 6.16】
#include"string.h"
main()
{ int k;
static char st1[15],st2[]="C Language";
printf("input a string:\n");
gets(st1);
k=strcmp(st1,st2);
if(k==0) printf("st1=st2\n");
if(k>0) printf("st1>st2\n");
if(k<0) printf("st1<st2\n");
}
本程序中把输入的字符串和数
组 st2中的串比较,比较结果
返回到 k中,根据 k值再输出结
果提示串。当输入为 dbase时,
由 ASCII 码可知,dBASE”大
于,C Language”故 k〉 0,输
出结果,st1>st2”。
6、测字符串长度函数 strlen
格式,strlen(字符数组名 )
功能:测字符串的实际长度 (不含字符串结束标
志‘ \0?) 并作为函数返回值。
【 例 6.17】
#include"string.h"
main()
{ int k;
static char st[]="C language";
k=strlen(st);
printf("The lenth of the string
is %d\n",k);
}
【 例 6.18】 把一个整数按大小顺序插入已排好序的数组中。
为了把一个数按大小插入已排好序的数组中,应首先确定排
序是从大到小还是从小到大进行的。设排序是从大到小进序
的,则可把欲插入的数与数组中各数逐个比较,当找到第一
个比插入数小的元素 i时,该元素之前即为插入位置。然后从
数组最后一个元素开始到该元素为止,逐个后移一个单元。
最后把插入数赋予元素 i即可。如果被插入数比所有的元素值
都小则插入最后位置。
本程序首先对数组 a中的 10个数从大到小排序并输出排序结
果。然后输入要插入的整数 n。再用一个 for语句把 n和数组
元素逐个比较,如果发现有 n>a[i]时,则由一个内循环把 i以
下各元素值顺次后移一个单元。后移应从后向前进行 (从 a[9]
开始到 a[i]为止 )。后移结束跳出外循环。插入点为 i,把 n赋
予 a[i]即可。 如所有的元素均大于被插入数,则并未进行过
后移工作。此时 i=10,结果是把 n赋于 a[10]。最后一个循环
输出插入数后的数组各元素值。
6.4 程序举例
main()
{
int
i,j,p,q,s,n,a[11]={127,3,6,
28,54,68,87,105,162,18};
for(i=0;i<10;i++)
{ p=i;q=a[i];
for(j=i+1;j<10;j++)
if(q<a[j])
{p=j;q=a[j];}
if(p!=i)
{
s=a[i];
a[i]=a[p];
a[p]=s;
}
printf("%d ",a[i]);
}
printf("\ninput number:\n");
scanf("%d",&n);
for(i=0;i<10;i++)
if(n>a[i])
{for(s=9;s>=i;s--)
a[s+1]=a[s];
break;}
a[i]=n;
for(i=0;i<=10;i++)
printf("%d ",a[i]);
printf("\n");
}
【 例 6.19】 在二维数组 a中选出各行最大的元素
组成一个一维数组 b。
a=( 3 16 87 65
4 32 11 108
10 25 12 37)
b=(87 108 37)
本题的编程思路是,在数组 A的每一行中寻找最大的元素,
找到之后把该值赋予数组 B相应的元素即可。程序如下,
main()
{
int a[][4]={3,16,87,65,4,32,11,108,10,25,12,27};
int b[3],i,j,l;
for(i=0;i<=2;i++)
{ l=a[i][0];
for(j=1;j<=3;j++)
if(a[i][j]>l) l=a[i][j];
b[i]=l;}
printf("\narray a:\n");
for(i=0;i<=2;i++)
{ for(j=0;j<=3;j++)
printf("%5d",a[i][j]);
printf("\n");}
printf("\narray b:\n");
for(i=0;i<=2;i++)
printf("%5d",b[i]);
printf("\n");
}
程序中第一个 for语句中
又嵌套了一个 for语句组
成了双重循环。外循环
控制逐行处理,并把每
行的第 0列元素赋予 l。
进入内循环后,把 l与后面
各列元素比较,并把比 l大
者赋予 l。
内循环结束时 l 即为该行最
大的元素,然后把 l值赋予
b[i]。等外循环全部完成时,
数组 b中已装入了 a各行中
的最大值。
6.5 本章小结
1.数组是程序设计中最常用的数据结构。数组可
分为数值数组 (整数组,实数组 ),字符数组以及
后面将要介绍的指针数组,结构数组等。
2.数组可以是一维的,二维的或多维的。
3.数组类型说明由类型说明符、数组名、数组长
度 (数组元素个数 )三部分组成。数组元素又称为
下标变量。数组的类型是指下标变量取值的类型。
4.对数组的赋值可以用数组初始化赋值,输入函
数动态赋值和赋值语句赋值三种方法实现。对数
值数组不能用赋值语句整体赋值、输入或输出,
而必须用循环语句逐个对数组元素进行操作。