




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第5章数组
5.1一维数组一维数组是由同类型数据按照线性次序顺次排列而成的构造类型。5.1.1一维数组的定义格式
类型说明符数组名[常量表达式];例如,语句“floata[6],b[10];”表示定义了一个可存放6个float类型数据的一维数组a和一个可存放10个float类型数据的一维数组b。说明:
①数组名应符合标识符的命名规则,例如,a12、gain_ratio是合法的数组名。
②方括号内的常量表达式表示数组元素的个数,即数组长度。可以是整型常量或整型常量表达式,也可以是符号常量,但不能包含变量。
③数组的数据类型既可以是基本类型,也可以是构造类型等。
④C编译系统为数组分配连续的内存单元。数组元素的相对次序由下标来表示。数组元素的下标是从0开始的整数。如上面定义的数组a的存储示意图如图5.1所示:5.1.2一维数组的引用在C语言中不能引用整个数组,只能引用单个数组元素。一个数组元素就是相当于一个变量,它的使用与同类型的普通变量是相同的。但数组元素特定的引用形式,会给编程带来很多方便。一维数组元素的引用形式为:
数组名[下标]说明:①数组名后方括号内是数组下标,下标表示该元素是数组的第几个元素。数组名后面的方括号内的内容只有在数组定义时才是数组的长度,其它时候都是数组下标。②数组元素的下标是整型的常量、变量或表达式。下标的取值范围是[0,数组长度-1]的整型值。③C程序运行时,编译系统并不检查数组元素的下标是否越界,需要编程人员自己保证数组元素的下标不要越界。
例如,语句floata[8];intx=2;数组元素a[0]、a[6]、a[5+1]、a[x]、a[3*x]都是合法引用;而a[-5]、a[8]、a[5.2]是非法的引用方式。注意,a[8]虽然非法,但是编译系统不报错。对a[8]的操作实际是对内存其他空间的操作,因此可能造成严重后果。
5.1.3一维数组的初始化数组的初始化就是给数组元素赋初值。数组的初始化操作既可以在数组定义之后进行,也可以在数组定义时完成。如果在数组定义之后进行初始化操作,则只能对每个数组元素一一赋值。例如,
intarr[10],i;for(i=0;i<10;i++)arr[i]=i;
如果在定义数组时完成数组的初始化操作,则需要将数组元素的初值依次放在一对花括弧中,并用赋值号与数组连接。定义数组时赋初值的形式为:类型说明符数组名[常量表达式]={初值列表};说明:①花括弧内各个初值之间用逗号分隔,数值类型必须与数组类型一致。系统将按初值的排列顺序给数组元素赋值。例如,语句“intarr[10]={0,1,2,3,4,5,6,7,8,9};”在定义数组arr的同时,将0、1、2、3、4、5、6、7、8、9依次赋给数组元素arr[0]、arr[1]、arr[2]、arr[3]、arr[4]、arr[5]、arr[6]、arr[7]、arr[8]、arr[9]。②花括弧中初值的数量必须小于等于数组长度。当初值数量小于数组长度时,数值型数组的后面没有初值的元素由系统自动赋值为0。例如,语句intarr[6]={0,1,2};arr[0]、arr[1]、arr[2]的值依次为0、1、2,其它元素即arr[3]、arr[4]、arr[5]的值均为0。③若给数组的所有元素赋初值,可以省略数组的长度。系统会根据所赋初值的个数确定数组的长度。例如,语句intarr[]={1,2,3,4,5,6,7,8,9,10};定义数组arr的长度为10,相当于语句“intarr[10]={1,2,3,4,5,6,7,8,9,10};”。5.1.4一维数组应用举例【例5.1】求10个整数的平均值。解题思路:输入10个整数→求和→再求平均值→输出结果。#include“stdio.h”voidmain(){inta[10],i;floatave,sum;printf("\npleaseenter10numbers:\n");
for(i=0;i<10;i++) /*输入元素*/scanf("%d",&a[i]);sum=0;for(i=0;i<10;i++) /*求和*/sum=sum+a[i];ave=sum/10; /*求平均值*/for(i=0;i<10;i++)printf("%6d",a[i]);printf("\naverage=%7.2f",ave);}
【例5.2】编写程序,找出10个整数中的最小值及其位置。解题思路:首先输入10个整数,然后找出其中的最小值及其位置,最后输出结果。其中最主要的功能是求最小值及其位置,完成这一功能的主要步骤为:①定义变量min记录最小值的位置即下标号,程序开始时假定第一个数为最小值,也就是位置min为0;②将min位置的数和数组的下一个数进行比较,如果min位置上的数大,则更改min值为更小数的位置;③比较完数组中所有的数,位置min上的数就是最小值,否则转向②继续执行。设数组x的10个数为3、2、7、1、4、8、5、11、4、9,则寻找最小值及其位置的过程应该为:32714851149初始min=0;↑min32714851149i=1时,x[i]<x[min],修改min指向1↑min32714851149i=2时,x[i]>x[min],min不变↑min32714851149i=3时,x[i]<x[min],修改min指向3↑min32714851149i=4时,x[i]>x[min],min不变↑
min……同样方式,将x[min]依次与x[5]、x[6]、x[7]、x[8]、x[9]相比较。每次比较均为x[min]小,因此min值不变,最终min的值为3。#include“stdio.h“/*例5.2程序*/voidmain(){intx[10],i,min;printf("\npleaseenter10numbers:");for(i=0;i<10;i++)/*输入10个元素*/scanf("%d",&x[i]);min=0;/*给min置初值*/for(i=1;i<10;i++)/*从第1个元素开始查找最小值位置*/if(x[i]<x[min])min=i;printf("最小的数为:x[%d]=%d",min,x[min]);/*输出最小值*/}输入3、2、7、1、4、8、5、11、4、9的程序运行结果为:pleaseenter10numbers:32714851149↙最小的数为:isx[3]=1类似地,请思考如何查找一个数列中最大值的位置
【例5.3】在递减的有序数列中,插入一个数x,使得数列仍然有序(如果有相同的数则不插入)。本题相当于在一个有序的数组中寻找合适的位置插入一个元素。问题的解决可分为两个步骤:①寻找插入位置:由于是递减的序列,所以插入位置应该是在第一个小于x的数组元素的前面(假定找到的位置为k);②如果第k个元素等于x,则不须插入,否则执行插入操作:第k个元素及其后面的元素都后移一位。插入元素在k位置。#defineN11#include"stdio.h"voidmain(){intarr[N],x,j,k;printf("\npleaseenterthearray(%d):",N-1);for(j=0;j<N-1;jscanf("%d",&arr[j]);++)/*输入数组元素*/printf("pleaseenterthenumber:");scanf("%d",&x);/*输入待插入元素*/for(j=0;x<=arr[j]&&j<N-1;j++);/*寻找插入位置*/k=j;/*k记录插入位置*/if(arr[k]==x&&k<N-1)/*数已存在,不执行插入,原样输出数组*/for(j=0;j<N-1;j++)printf("%4d",arr[j]);else{for(j=N-2;j>=k;j--)arr[j+1]=arr[j];/*移动插入点以后的元素*/arr[k]=x;/*插入元素*/printf("thearrayis:\n");for(j=0;j<N;j++)printf("%4d",arr[j]);/*输出数组*/}}若数列为67、43、39、33、30、28、26、15、10、7,输入27时的程序运行结果为:pleaseenterthearray(10):6743393330282615107↙pleaseenterthenumber:27↙thearrayis:674339333028272615107请考虑,移动元素可不可以从前面的元素开始移动(即先移动插入位置的元素,最后移动最后一个元素),为什么?如果可以有重复数据,程序该如何编写?【例5.4】用冒泡法对10个数进行排序(由小到大)。冒泡法思路是,从前到后扫描数据序列,比较相邻两个数的大小,将小的数调到前头,大的数沉底。如图5.2988888895542559444444922222290000009第1次第2次第3次第4次第5次结果假设有6个数据,第一次将8和9进行比较后对调,第二次将9(下沉了一位)和5进行比较后对调,第三次……,直到所有的数均比较完毕后,9已沉到了最底层,这时,最小的数0上浮了一位,经第一趟(共5次)后,已得到最大的数。然后进行第二趟对余下来的数据进行比较我,第二趟要比第一趟少比较1次,即只需4次即可比较出最大的数。依次类推,比较完毕后得到的就是按顺序排列的数据。#include“stdio.h“/*例5.4程序
*/voidmain(){inta[10];inti,j,t;printf("\ninput10numbers:\n");for(i=0;i<10;i++) scanf("%d",&a[i]);/*读入10个数,放入a数组中*/printf("\n");for(j=0;j<9;j++)/*控制比较的趟数,共9趟*/for(i=0;i<9-j;i++)/*一趟的比较,沉一个最大的数*/if(a[i]>a[i+1]) {t=a[i];a[i]=a[i+1];a[i+1]=t;}printf("thesortednumbers:\n");for(i=0;i<10;i++)printf("%d",a[i]); }5.2二维数组含有两个下标的数组称为二维数组,其中的数据是按照行列的格式排列的,即数据分为若干行、若干列。C语言规定,二维数组的行下标和列下标均是从0开始计算的。5.2.1二维数组的定义格式类型说明符数组名[常量表达式1][常量表达式2];例如,语句“intb[4][3];”表示定义了一个具有4行3列的整型数据的二维数组b。说明:①二维数组定义中,数组名、数据类型的定义方式和一维数组相同,不同的只是数组名后面紧跟两个方括号,两个常量表达式,常量表达式1表示数组的行数,常量表达式2表示每行数据的个数,即列数。数组的元素个数就是两个常量表达式之积。②二维数组只是在逻辑上是二维的,从存储上看,二维数组仍是存储在一维线性空间。C语言中,按照行优先方式存储二维数组,即先存放第0行的元素,再连续存放第1行的元素……。例如,上面定义的b是一个4行3列的数组,它在内存中的存储示意图如图5.3,是一维线性存储空间。5.2.2二维数组的引用二维数组也只能引用单个数组元素,不能引用整个数组。二维数组元素的引用形式为:数组名[下标1][下标2]
二维数组的下标可以是整型的变量、常量或表达式。第一维下标的取值范围是[0,第一维长度-1],第二维下标的取值范围是[0,第二维长度-1]。例如,在语句“intb[4][3];”之后引用数组b的元素。b[0][2]、b[1+1][1]、b[i][j](i、j为整型变量)是合法的引用方式;而b[2][3]、b[1.2][2]、b[6][0]、b[1,2]、b[2],[0]、b(1,2)、b(3)(1)是非法的引用方式。5.2.3二维数组的初始化
二维数组的初始化既可以在数组定义之后进行,也可以在定义数组的同时完成。
如果定义之后进行数组的初始化操作,则只能对每个数组元素一一赋值,例如,intarr[4][10],i,j;for(i=0;i<4;i++)for(j=0;j<10;j++)arr[i][j]=0;如果在定义数组时完成数组的初始化操作,赋值格式有如下两种:①将数组元素的初值依次放在一对花括弧中并用赋值号与数组连接。具体格式为:
类型说明符数组名[常量表达式1][常量表达式2]={初值列表};花括弧内各个初值之间用逗号分隔,初值类型必须与数组类型一致。系统自动按数组元素在内存的顺序将初值依次赋给相应的元素。若数值型数组的初值数量不足时,将0赋给其余数组元素。例如,语句“intx[2][3]={1,2,3,4,5};”之后,系统自动按数组x的元素在内存的顺序将初值依次赋给相应的元素,即x[0][0]=1,x[0][1]=2,x[0][2]=3,x[1][0]=4,x[1][1]=5。其余元素被自动赋值为0:x[1][2]=0。②赋初值时,每一行的初值放在一个花括号中,所有行的初值再放在一个花括号中。具体格式为:类型说明符数组名[常量表达式1][常量表达式2]={{第0行初值列表},{第1行初值列表},…};系统将第一个花括号内数据依次赋值给数组的第0行,将第二个花括号内数据依次赋值给数组的第1行,依次类推。例如,语句“intx[4][4]={{1,2,3,4},{4,5,6},{},{7}};”之后,系统将1、2、3、4依次赋给x[0][0]、x[0][1]、x[0][2]和x[0][3];4、5、6依次赋给x[1][0]、x[1][1]和x[1][2],没有列出初值的元素,系统自动赋0;对应第2行的“{}”,系统给x[2][0]、x[2][1]、x[2][2]和x[2][3]均赋值0;第3行对应{7},则系统将7赋值给x[3][0],而x[3][1]、x[3][2]和x[3][3]均被系统赋值为0。注意:在赋初值时需指定第二维数组长度,可省略第一维的长度。编译系统会根据赋初值的情况,自动得到第一维的长度。例如语句“intx[][3]={{1,2,3},{4}};”,编译系统可分析出第一维的长度是2。5.2.4二维数组应用举例【例5.5】将一个二维数组行和列元素互换后,存到另一个二维数组中,如图5.4所示。
12314a=b=2545636
#include“stdio.h“/*例5.5程序*/voidmain(){inta[2][3]={{1,2,3},{4,5,6}};intb[3][2],i,j;printf("arraya:\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("arrayb:\n");for(i=0;i<=2;i++){for(j=0;j<=1;j++) printf("%5d",b[i][j]);printf("\n");}}5.3字符数组实际应用中除要求程序处理数值型数据外,还要求处理文字型数据。文字型数据不是单个的字符,而是字符串。C系统没有提供字符串变量,字符串通常用字符型数组来存放、处理。5.3.1字符数组的定义和引用字符数组是指数组元素为字符型的数组。字符数组的定义、引用、初始化方式和其它类型数组非常类似。但是由于字符数组是文字型数据,因此其使用方式又有不同之处。一维字符数组的定义格式为:
char数组名[常量表达式];例如,语句“charstr1[8];”定义了一个可存放8个字符的一维数组str1。二维字符数组可以存放多个字符串。二维字符数组的定义格式为:
char数组名[常量表达式1][常量表达式2];
例如,语句“charstr2[6][80];”定义了一个二维字符数组,可存放6个字符串的,每串长度不能超过80个字符(包括字符串结束符)。
字符数组元素也可通过数组名和下标引用。例如,str1[6]、str2[2][7]、str1[i]、str2[j][k]都是合法的字符数组元素的引用(设i,j,k是整型变量)。
字符数组也可以在定义时初始化,方法和其它类型的数组一样,例如,charstr1[3][8]={{'r','e','d'},{'y','e','l','l','o','w'},{'g','r','e','e','n'}};注意:若没有对字符数组全部元素赋值,编译系统会对剩余的元素自动赋值为空字符。空字符用'\0'来表示,是ASCII码值为0的字符,表示什么都不做,也不显示。
在定义字符数组之后,只能逐个给数组元素赋值。charstr2[8];str2[0]='a';str2[1]='b';str2[2]='c';str2[3]='d';
对字符数组元素的操作只要符合字符类型的操作规则即可。【例5.8】输出一个数字金字塔图形。#include"stdio.h"voidmain(){chardiamond[][11]={{'','','','','','1'}, {'','','','','2','2','2'}, {'','','','3','3','3','3','3'}, {'','','4','4','4','4','4','4','4'}, {'','5','5','5','5','5','5','5','5','5'}, {'6','6','6','6','6','6','6','6','6','6','6'} };inti,j;for(i=0;i<6;i++) {for(j=0;j<11;j++) printf("%c",diamond[i][j]); printf("\n"); }}【例5.9】将一行字符中所有字母替换为在字母表中其后的第三个字母,即a替换为d、z替换为c,然后输出。#include"stdio.h"#include"string.h"voidmain(){charstr[80],i=0;printf("pleaseenterthecharacters:");while((str[i]=getchar())!=‘\n’)i++;/*输入字符序列,直到 车时结束*/for(i=0;str[i]!='\n';i++){if(str[i]<='w'&&str[i]>='a')str[i]=str[i]+3;if(str[i]<='z'&&str[i]>='x')str[i]=str[i]-23;if(str[i]<='W'&&str[i]>='A')str[i]=str[i]+3;if(str[i]<='Z'&&str[i]>='X')str[i]=str[i]-23;}for(i=0;str[i]!='\n';i++)/*输出字符序列*/printf("%c",str[i]);}5.3.2字符串和字符数组1.字符串的表示编程者用字符数组处理字符串时,关心就不是数组的长度,而是有效字符串的长度。C语言中不保存字符串的长度,因此需要在字符串末尾加字符串结束标志
空字符'\0'以表示字符串结束。
对于字符串常量,编译系统处理时会自动在字符串末尾处加上'\0'。因此,含有n个字符的字符串常量在内存中占n+1个字节的空间,第n+1个字节存放'\0'。字符串常量和字符常量是不同,主要区别有两点:①形式不同,字符串常量是用双引号引起来的字符序列,字符序列可以为空,也可以是一个或多个字符;而字符常量是用单引号引起来的单个字符;
②存储不同,字符串常量要占用(字符串长度+1)个字节;而字符常量占用一个字节空间存放其本身。例如,'s'是字符常量,值为字母s,在内存保存的是字母s的ASCII码值,占一个字节;而"s"表示含有一个字母s的字符串,在内存保存的是字母s和空字符'\0'的ASCII码值,占两个字节。""表示空串,在内存中保存的是空字符'\0'的ASCII码值,占一个字节。"
"表示一个含有一个空格的字符串,在内存中占两个字节;''表示空格字符,在内存中占一个字节。
注意:对于字符串数组,系统不自动添加结束标志'\0',如例5.10。【例5.10】从键盘输入一行字符,存放在字符数组中,然后输出。#defineN80#include"stdio.h"main(){charstr[N];inti,j;printf("pleaseenterthecharacters:");for(i=0;(str[i]=getchar())!=‘\n’;i++);/*输入字符序列,当输入 字符为回车时结束*/str[i]='\0';/*添加字符串结束标志*/for(i=0;str[i]!='\0';i++)/*输出字符序列*/printf("%c",str[i]);}2.字符串常量赋给字符数组若在定义字符数组的同时赋初值,则可将字符串常量赋给它。例如,charc[20]={"Thegreatwall"};习惯上可以省略花括号,上面定义写为:
charc[20]="Thegreatwall";数组c在内存中存储的示意图如图。Thegreatwall\0\0\0\0\0\0012345678910111213141516171819说明:①若定义字符数组时完成赋初值,则可以在定义中省略数组的长度。系统会根据所赋字符串常量的实际长度来确定字符数组的长度。如上述定义也可写为:charc[]="Thegreatwall";系统会自动确定数组c的长度为15。②字符串常量末尾处有系统自动加的结束标志'\0',所以要求数组长度比字符串长度至少大1。例如,charc[14]="Thegreatwall";这条语句中数组c不能满足字符串长度。③除了数组定义时可以将字符串直接付给字符数组外,其它时刻只能对元素进行赋值。例如,不能用语句“c="string";”对字符数组c赋值。【例5.11】写出程序结果,并考虑原因。#include"stdio.h"main(){charstr1[]="Thisisastring";charstr2[]={'T','h','i','s','','i','s','','a','','s','t','r','i', 'n','g','\0'};charstr3[]={'T','h','i','s','','i','s','','a','','s','t','r','i', 'n','g'};inti;for(i=0;str1[i]!='\0'&&i<20;i++)printf("%c",str1[i]);printf("\nlength:%3d\n",i);for(i=0;str2[i]!='\0'&&i<20;i++)printf("%c",str2[i]);printf("\nlength:%3d\n",i);for(i=0;str3[i]!='\0'&&i<20;i++)printf("%c",str3[i]);printf("\nlength:%3d\n",i);}程序运行结果为:Thisisastringlength:16Thisisastringlength:16ThisisastringΦ
↔☺length:20(注意这里Φ
↔☺是四个未知字符造成的)charstr1[]="Thisisastring";和charstr2[]={'T','h','i','s','','i','s','','a','','s','t','r','i','n','g','\0'}是等效的,在内存中存储了字符串"Thisisastring"和一个'\0',数组长度都为17。但charstr3[]={'T','h','i','s','','i','s','','a','','s','t','r','i','n','g'},这条语句在内存中存放了'T'、'h'、'i'、's'、''、'i'、's'、''、'a'、''、's'、't'、'r'、'i'、'n'、'g'16个字符,数组长度为16。因为输出str3时没有找到结束标志,超出了数组范围,所以输出了四个未知字符。5.3.3常用字符串处理函数
为了简化程序设计的复杂度,C语言提供了大量处理字符串的库函数。这里仅介绍几个常用的函数。
1.字符串输入函数gets
格式:gets(字符数组)
功能:接收从键盘输入的一个字符串(可包含空格),存放在字符数组中。函数的返回值是字符数组的起始地址。例如,在语句“char
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 边缘计算融合优化-深度研究
- 量子力学基础-深度研究
- 跨区域溯源协同机制-深度研究
- 影视项目聘用编剧合同模板
- 合同清淤泥合同(2025年版)
- 2024年新材料产业园区项目资金需求报告代可行性研究报告
- 2024年汽车项目资金筹措计划书代可行性研究报告
- 乡村信息化管理合同书
- 媒体内容营销推广合同
- 监控系统安装实施合同
- 2025年南昌理工学院单招职业技能测试题库完整
- 2025年黑龙江省安全员A证考试题库附答案
- 2025年黑龙江农业工程职业学院单招职业适应性测试题库及答案1套
- DB32T-工业有机废气治理用活性炭技术要求
- 2024年辅警招聘考试试题库含完整答案(各地真题)
- TCALC 003-2023 手术室患者人文关怀管理规范
- 2024春苏教版《亮点给力大试卷》 数学四年级下册(全册有答案)
- 润滑油存放区应急预案
- 25题退役军人事务员岗位常见面试问题含HR问题考察点及参考回答
- 浙江心理健康教育B证材料(教案设计)
- 人教版数学三年级下册第一单元《位置与方向(一)》单元测试卷[附答案]
评论
0/150
提交评论