C语言程序设计教程第五章数组.docx
《C语言程序设计教程第五章数组.docx》由会员分享,可在线阅读,更多相关《C语言程序设计教程第五章数组.docx(20页珍藏版)》请在冰豆网上搜索。
C语言程序设计教程第五章数组
第五章数组
1.教学内容:
§5.1一维数组
5.1.1一维数组的定义
5.1.2一维数组的初始化
5.1.3数组元素的引用
5.1.4数组作为函数参数
5.1.5一维数组应用举例
§5.2二维数组和多维数组
5.2.1二维数组和多维数组的概念及其定义
5.2.2二维数组和多维数组的引用
5.2.3二维数组和多维数组的初始化
5.2.4二维数组程序举例
§5.3字符数组和字符串
5.3.1字符串和字符串的存储方法
5.3.2字符数组的初始化
5.3.3字符串的输入
5.3.4字符串的输出
5.3.5字符串运算函数
5.3.6二维的字符数组
5.3.7字符数组应用举例
2.教学目的及要求:
1)掌握数组的概念和使用
2)掌握数组初始化的方法
3)掌握字符数组和字符串的应用
3.教学重点:
1)一维数组
2)二维数组和多维数组
3)字符数组
第五章数组
数组是指一组具有相同数据类型的有序数据的集合。
用一个统一的名字标识这组数据,用下标来指示数组中元素的序号。
一个数组元素也称一个下标变量,其用法与普通的变量使用方法相同。
§5.1一维数组
一维数组是只有一个下标变量的数组。
5.1.1一维数组的定义
定义方式:
类型标识符数组名[下标常量表达式]
【例】:
inta[10]
定义一个数组,数组名a,有10个元素,每个元素的类型均为int。
这10个元素分别是:
a[0]、a[1]、a[2]、a[3]……a[8]、a[9]。
注意:
(1)C语言中,数组下标从0开始。
(2)C语言不允许对数组的大小做动态定义,
如:
intn;
scanf("%d",&n);
inta[n];/*
*/
因为,在编译时,C编译器根据已知数组大小分配内存。
5.1.2一维数组的初始化
在定义数组时对各元素指定初始值,称为数组的初始化。
1、一般初始化
用花括号把要赋给各元素的初始值括起来,数据间用逗号分隔。
【例】:
staticinta[9]={1,2,3,4,5,6,7,8,9};
a[0]=1,a[1]=2,a[2]=3,……a[8]=9
2、部分元素初始化
【例】:
staticinta[10]={1,2,3,4,5};
只对前5个元素赋初值,后5个元素未指定初值,系统默认为0。
3、全部元素均初始化为0,不允许简写。
【例】:
staticinta[10]={0,0,0,0,0,0,0,0,0,0};
不能简写为:
staticinta[10]={0*10};
注意:
当程序不给数组指定初始值时,编译器作如下处理:
(1)编译器自动把静态数组的各元素初始化为0或空字符。
(2)编译器不为动态数组自动指定初始值,其初值不可预料。
4、如果全部元素均指定初值,定义中可以省略元素的个数。
【例】:
staticinta[5]={1,2,3,4,5};
可写成:
staticinta[]={1,2,3,4,5};
5.1.3数组元素的引用
C语言规定,不能引用整个数组,只能逐个引用元素。
引用形式:
数组名[下标]
【例】:
使数组元素a[0]~a[9]的值为0~9,然后逆序输出。
main()
{inti,a[10];
for(i=0;i<=9;i++)
a[i]=i;
for(i=9;i>=0;i--)
printf("%d",a[i]);
}
运行输出:
9876543210
注意:
⑴下标可用整常数或整型表达式,其起始值为0。
⑵在引用时应注意下标的值不要超过数组的范围。
C编译不检查下标是否超界,即不指出“下标超界”的错误。
5.1.4数组作为函数参数
1、数组元素用作函数实参,其用法与普通变量完全相同:
在发生函数调用时,把数组元素的值传送给形参,实现单向值传送。
【例】:
写一函数,统计字符串中字母的个数。
/*功能:
数组元素作为函数实参*/
intisalp(charc)
{if(c>='a'&&c<='z'||c>='A'&&c<='Z')
return
(1);
elsereturn(0);
}
main()
{inti,num=0;
charstr[255];
printf("Inputastring:
");
gets(str);/*从标准设备读入字符串,并放入str指向的数组*/
for(i=0;str[i]!
='\0';i++)
if(isalp(str[i]))num++;
puts(str);/*把str指向的字符串输出到标准设备*/
printf("num=%d\n",num);
getch();/*从标准输入设备读入下一个字符*/
}
说明:
用数组元素作实参时,只要数组类型和函数的形参类型一致即可,并不要求函数的形参也是下标变量。
换句话说,对数组元素的处理是按普通变量对待的。
2、数组名作函数参数时,既可以作形参,也可以作实参。
数组名作函数参数时,要求形参和相对应的实参都必须是类型相同的数组(或指向数组的指针变量),都必须有明确的数组说明
【例】:
已知某个学生5门课程的成绩,求平均成绩。
floataver(floata[])/*求平均值函数*/
{inti;
floatav,s=a[0];
for(i=1;i<5;i++)s+=a[i];
av=s/5;
returnav;
}
main()
{floatsco[5],av;
inti;
printf("\ninput5scores:
\n");
for(i=0;i<5;i++)scanf("%f",&sco[i]);
av=aver(sco);/*调用函数,实参为数组名*/
printf("averagescoreis%5.2f\n",av);
getch();/*从标准输入设备读入下一个字符*/
}
说明:
⑴组名作函数参数,应该在调用函数和被调用函数中分别定义数组,且数据类型必须一致,否则结果将出错。
⑵C编译系统对形参数组长度不作检查,所以形参数组可以不指定长度。
例如,本例中的形参数组a[]。
⑶如果指定形参数组的长度,则实参数组的长度必须大于等于形参数组,否则因形参数组的部分元素没有确定值而导致计算结果错误。
⑷以数组名作参数时,采取的不是“值传送”方式,而是“地址传送”方式,即把实参数组的起始地址传给形参数组,这样形参数组就和实参数组共占一段内存单元。
如上例可表示为:
a[0]
a[1]
a[2]
a[3]
a[4]
78
Sco[0]
Sco[1]
Sco[2]
Sco[3]
Sco[4]
75
86
95
68
5.1.5一维数组应用举例
【例】:
输入10个数,用“起泡法”对10个数排序(由小到大)。
“起泡法”算法:
以六个数9、8、5、4、2、0为例。
第1趟比较
第2趟比较
算法过程:
第1趟比较后,剩5个数未排好序;两两比较5次
第2趟比较后,剩4个数未排好序;两两比较4次
第3趟比较后,剩3个数未排好序;两两比较3次
第4趟比较后,剩2个数未排好序;两两比较2次
第5趟比较后,全部排好序;两两比较1次
算法结论:
对于n个数的排序,需进行n-1趟比较,第j趟比较需进行n-j次两两比较。
程序流程图:
(用两层嵌套循环实现)
程序:
设需排序的数有10个,定义数组大小为11,使用a[1]~a[10]存放10个数,a[0]不用。
main()
{inta[11];/*用a[1]~a[10],a[0]不用*/
inti,j,t;/*i,j作循环变量,t作两两比较的临时变量*/
printf("input10numbers:
\n");
for(i=1;i<11;i++)
scanf("%d",&a[i]);/*输入10个整数*/
printf("\n");
for(j=1;j<=9;j++)/*第j趟比较*/
for(i=1;i<=10-j;i++)/*第j趟中两两比较10-j次*/
if(a[i]>a[i+1])/*交换大小*/
{t=a[i];a[i]=a[i+1];a[i+1]=t;}
printf("thesortednumbers:
\n");
for(i=1;i<11;i++)
printf("%d",a[i]);
}
§5.2二维数组和多维数组
5.2.1二维数组和多维数组的概念及其定义
如果一维数组的每一个元素是类型相同的一维数组时,就形成了二维数组。
二维数组是有二个下标变量的数组。
第一个下标称为行下标,第二个下标称为列下标,因此,二维数组可看成是一个二维表。
二维数组的一般定义形式为:
类型标识符数组名[常量表达式1][常量表达式2]
二维数组的理解:
【例】:
a[3][4]
二维数组a[3][4]理解为:
有三个元素a[0]、a[1]、a[2],每一个元素是一个包含4个元素的数组。
二维数组的元素在内存中的存放循序:
【例】:
a[3][4]
按行存放。
即:
先顺序存放第一行的元素,再存放第二行的元素。
二维数组的元素a[i][j]在数组中的位置计算公式:
设有一个m×n的二维数组,元素a[i][j]在数组中的位置计算公式为:
i×n+j+1
多维数组是有多个下标变量的数组。
多维数组的一般定义形式为:
类型标识符数组名[常量表达式1][常量表达式2]…[常量表达式n]
三维数组:
floata[2][3][4]在内存中的存放顺序:
a[0][0][0]→a[0][0][1]→a[0][0][2]→a[0][0][3]→
a[0][1][0]→a[0][1][1]→a[0][1][2]→a[0][1][3]→
a[0][2][0]→a[0][2][1]→a[0][2][2]→a[0][2][3]→
a[1][0][0]→a[1][0][1]→a[1][0][2]→a[1][0][3]→
a[1][1][0]→a[1][1][1]→a[1][1][2]→a[1][1][3]→
a[1][2][0]→a[1][2][1]→a[1][2][2]→a[1][2][3]
5.2.2二维数组和多维数组的引用
二维数组元素的引用形式为:
数组名[下标1][下标2]
【例】:
floata[2][3];
有6个元素,按如下方式引用各元素:
a[0][0]、a[0][1]、a[0][2]、a[1][0]、a[1][1]、a[1][2]
注意:
数组floata[2][3]中无元素a[2][3]。
(下标从0始)
5.2.3二维数组和多维数组的初始化
㈠二维数组的初始化
1、分行对各元素赋值,如:
staticinta[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
2、全部数据写在一个花括号内,如:
staticinta[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
3、只对部分元素赋值。
如:
staticinta[3][4]={{1},{5},{9}};
仅对a[0][0]、a[1][0]、a[2][0]赋值,其余元素未赋值(对于静态数组,未赋值元素指定初值0;对于动态数组,未赋值元素的初值是随机的)。
4、如果对全部元素赋初值,则第一维的长度可以不指定,但必须指定第二维的长度。
【例】:
staticinta[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
与下面定义等价:
staticinta[][4]={1,2,3,4,5,6,7,8,9,10,11,12};
㈡多维数组的初始化
与二维数的初始化相似。
5.2.4二维数组程序举例
【例1】:
将一个二维数组行和列交换,存到另一个二维数组中。
如:
算法:
b[j][i]=a[i][j]
程序:
main()
{staticinta[2][3]={{1,2,3},{4,5,6}};
staticintb[3][2],i,j;
printf("arraya:
\n");
for(i=0;i<=1;i++)/*0~1行*/
{for(j=0;j<=2;j++)/*0~2列*/
{printf("%5d",a[i][j]);
b[j][i]=a[i][j];/*行、列交换*/
}
printf("\n");/*输出一行后换行*/
}
printf("arrayb:
\n");
for(i=0;i<=2;i++)
{ for(j=0;j<=1;j++)
printf("%5d",b[i][j]);
printf("\n");
}
}
【例2】:
有一个3×4的矩阵,编程序求出其中值最大的那个元素的值及其所在的行号和列号。
算法:
⑴把第一个元素a[0][0]作为临时最大值max;
⑵把临时最大值max与每一个元素a[i][j]进行比较,若a[i][j]>max,把a[i][j]作为新的临时最大值,并记录下其下标i和j。
当全部元素比较完后,max是整个矩阵全部元素的最大值。
流程:
程序:
main()
{inti,j,row=0,colum=0,max;
staticinta[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);
}
注意:
本例中得到的行列值从0始。
§5.3字符数组和字符串
字符数组:
存放字符数据的数组。
每一个元素数组存放一个字符。
5.3.1字符串和字符串的存储方法
字符串是指若干有效字符(指系统允许使用的字符)的序列。
C语言允许的字符串可包括字母、数字、专用字符、转字符等。
它用双引号括起来。
C语言中没有字符串变量。
字符串存放在一个字符型数组中。
【例】:
将字符串“computer”存入字符数组str中。
定义字符数组:
Charstr[8];
采用赋值运算,将字符一个一个地赋给字符数组各元素:
Str[0]=’c’;Str[1]=’o’;Str[2]=’m’;….
…Str[7]=’r’;str[8]=’\0’;
存储字符串示意图:
Str[0]Str[1]Str[2]………Str[7]Str[8]
c
o
m
p
u
t
e
R
\0
C语言规定:
以“\0”字符作为字符串结束标志。
“\0”是指ASCII为0的字符,它不是一个普通的可显示字符,而是一个“空操作”字符,它不进行任何操作,只是作为一个标志。
5.3.2字符数组的初始化
1、逐个为数组元素指定初值
如:
staticcharc[10]={'I','','a','m',
'','h','a','p','p','y'};
2、初始化数据少于数组长度,多余元素自动为“空”。
如:
staticcharc[10]={'c','','p','r',
'o','g','r','a','m'};
3、指定初值时,若未指定数组长度,则长度等于初值个数。
如:
staticcharc[]={'I','','a','m','','h','a','p','p','y'};
4、对字符数组指定一个字符串初值
如:
staticcharc[]={“Iamhappy”}
注意:
字符数组的元素个数应该足够大,能容纳所存的字符和“\0”。
5.3.3字符数组的引用
引用一个元素,得到一个字符。
【例】:
输出一个字符串。
main()
{staticcharc[10]={'I','','a','m','','a','','b','o','y'};
inti;
for(i=0;i<10;i++)
printf("%c",c[i]);
printf("\n");
}
输出结果:
Iamaboy
5.3.4字符串的输入\输出两种方法:
1、用“%c”格式符逐个输入输出。
2、用“%s”格式符按字符串输入输出。
【例】:
staticcharc[6];
scanf("%s",c);
printf("%s",c);
注意:
(1)输入时,遇回车键结束,但获得的字符中不包含回车键本身,而是在字符串末尾添'\0'。
因此,定义的字符数组必须有足够的长度,以容纳所输入的字符。
(如,输入5个字符,定义的字符数组至少应有6个元素)。
(2)一个scanf函数输入多个字符串,输入时以“空格”键作为字符串间的分隔。
【例1】:
staticcharstr1[5],str2[5],str3[5];
scanf("%s%s%s",str1,str2,str3);
输入数据:
Howareyou?
str1、str2、str3获得的数据见下图:
【例2】:
staticcharstr[13];
scanf("%s",str);
输入:
Howareyou?
结果:
仅“How”被输入数组str
如要想str获得全部输入(包含空格及其以后的字符),程序应设计为:
staticcharc[13];
inti;
for(i=0;i<13;i++)c[i]=getchar();
(3)C语言中,数组名代表该数组的起始地址,因此,scanf()函数中不需要地址运算符&。
(在TurboC中,加上&运算符也可以)。
staticcharstr[13];
scanf("%s",str);
scanf("%s",&str);/*错误*/
(4)gets()函数:
输入字符串到数组。
【例】:
staticcharstr[12];
gets(str);
注意:
gets()一次只能输入一个字符串。
而scanf()可以输入几个字符串。
(5)输出时,遇'\0'结束,且输出字符中不包含'\0'。
(6)“%s”格式输出字符串时,printf()函数的输出项是字符数组名,而不是数组元素名。
【例】:
staticcharc[6]="China";
printf("%s",c);printf("%c",c[0]);
printf("%s",c[0]);/*
*/
(7)“%s”格式输出时,即使数组长度大于字符串长度,遇'\0'也结束。
【例】:
staticcharc[10]={"China"};
printf("%s",c);/*只输出5个字符*/
(8)“%s”格式输出时,若数组中包含一个以上'\0',遇第一个'\0'时结束。
(9)puts()函数:
输出字符串(以'\0'结尾)。
注意:
puts()一次只能输出一个字符串。
而printf()可以输入输出几个字符串。
【例】:
staticcharc[6]="China";
/*printf、puts均以'\0'结尾*/
printf("%s\n",c);
/*printf需要格式控制符%s*/
puts(c);
/*puts不需要格式控制符,且自动换行*/
5.3.5字符串运算函数
1、strcat():
连接字符串。
格式:
strcat(字符串1,字符串2);
把“字符串2”连接到“字符串1”的后面。
2、strcpy():
字符串拷贝。
格式:
strcpy(字符串1,字符串2);
把“字符串2”的值拷贝到“字符串1”中。
3、strcmp():
字符串比较。
格式:
intstrcmp(字符串1,字符串2);
比较规则:
逐个字符比较ASCII码,直到遇到不同字符或'\0',比较结果是该函数的返回值。
strcmp()返回值
字符串1<字符串2
<0
字符串1==字符串2
=0
字符串2>字符串2
>0
长度不同的字符串也可以进行比较,比较结果当然是“不同”。
注意:
字符串只能用strcmp函数比较,不能用关系运算符“==”比较。
【例】:
if(strcmp(str1,str2)==0)printf("yes");
if(!
strcmp(str1,str2))printf("equal");
if(str1==str2)printf("yes");/*
*/
4、trlen():
测试字符串长度函数
格式:
strlen(字符串);
【例】:
strlen(“computer”)结果:
8
5、strlwr():
将字符串中的大写字母转换为小写字母(lwr:
lowercase小写)。
6、strupr():
将字符串中的小写字母转换为大写字母(upr:
uppercase大写)。
注意:
以上函数均是库函数,使用时必须用#include语句包含头文件。
5.3.6二维的字符数组
二维数组可认为是由若干个一维数组所组成的,也知道一个一维数组可存放一个字符串,因此,一个N×M的二维数组可存放N个最大长度为M-1的字符串。
其中要留一个位置存放“\0”。
【例】:
staticcharstr[3][6]={“China”,“Japan”,“Korea”}
存放在str中的字符串示意图:
C
h
I
n
a
\0
J
a
p
a
n
\0
K
o
r
e
a
\0
Str[0]
Str[1]
Str[2]
二维字符数组元素的引用与二维数组的引用相同。
【例】:
一个班级中有若干名学生。
今输入一个学生名,要求查询该学生是否属于该班,输出相应的信息。
[程序]:
#defineMAX3
#defineLEN10
main()
{intI,flag=0;
charname[LEN];
staticcharlist[MAX][LEN]={“Zhang”,“Wang”,“Li”};
printf(“Enteryourname:
”);
gets(name);
for(I=0,Iif(strcmp(list[I],name)==0)flag=1;
if(flag==1)
printf(“%sisinourclass\n”,name);
else
printf(“%sisnotinourclass\