资源描述:
《第7章 高级语言程序设计C--数组ppt课件.ppt》由会员上传分享,免费在线阅读,更多相关内容在教育资源-天天文库。
第七章数组 第七章数组(array)内容提要数组的概念一维数组的定义与使用二维数组的定义与使用字符数组与字符串多维数组 7.1数组的基本概念:数组(array)是n(n≥1)个具有相同数据类型的数据元素a0,a1,…,an-1构成的一个有序序列(集合)。数组由一个统一的数组名来标识,数组中的某个序号元素由数组名和相应的一组下标(index)来标识。标记某个数组元素的下标个数就决定了数组的维数,即下标个数为一个,则为一维数组,下标个数为二个,则为二维数组等。7.1数组的概念 数组中元素之间的关系:逻辑关系:数组用来描述n(n≥1)个具有相同数据类型的数据元素a0,a1,…,an-1构成的一个有序的集合,其中各个数据元素之间存在着确定的逻辑关系:ai(0≤i≤n-1)为ai+1的前驱(元素),ai+1为ai的后继(元素),只有数组中的第一个元素(首元素)a0没有前驱,也只有数组中的最后一个元素(末元素或尾元素)ai+1没有后继。7.1数组的概念 元素之间存在的这种线性逻辑关系,可以用下图描述之:7.1数组的概念a0a1ai-1aiai+1an-2an-1······数组的末元素数组的首元素 存储关系(物理关系):构成数组的各元素按先行后列、同行则先低列后高列的次序依次存储在一块地址连续的内存单元中,最低地址对应首元素,最高地址对应末元素。对于一维数组,由于只有一行,则元素按它们序号的先后,依次存储在一块地址连续的内存单元中,最低地址对应首元素,最高地址对应末元素。7.1数组的概念 存储关系(物理关系):例如:定义一个一维数组inta[10]={1,2,3,4,5,6,7,8,9,10};,则这些元素的存储位置按其逻辑关系的前后依次存储在连续(从低地址向高地址)的存储空间中。7.1数组的概念12345678910低地址端高地址端a[0]a[9] 存储关系(物理关系):对于二维数组,则按先(第1维)行后列(第2维),同行按先低列后高列的次序,依次存储在一块连续的存储单元中。例如,定义一个二维数组intb[2][5]={1,2,3,4,5,6,7,8,9,10};,则这些元素的存储位置也按其逻辑关系的先后次序依次存储在连续(从低地址向高地址)的存储空间中。7.1数组的概念12345678910低地址端高地址端a[0][0]a[1][4]a[0][4]a[1][0] 存储关系(物理关系):类似地,对于多维数组,则按先第1维,后第2维,…,同维则先低后高的次序依次存储在一块地址连续的内存单元中,最低地址对应首元素,最高地址对应末元素。即,对于数组(一维、二维或多维)中的各元素,逻辑上相邻的两个元素在物理存储位置上也相邻,前驱元素的存储位置位于后继元素之前(低端地址)。7.1数组的概念 元素的存储地址计算基于数组元素的存储方式,我们可以很容易推导出根据数组首元素的地址,计算任意一元素存储地址的两个公式:(1)一维数组Typea[N]的元素a[i]的存储地址=数组起始地址+i×sizeof(元素类型)(2)二维数组Typea[M][N]中元素a[i][j]的存储地址=首元素的存储地址+(i×N+j)×sizeof(Type)其中Type为数组元素的类型,即数组的基类型。7.1数组的概念 第七章数组(array)内容提要数组的概念一维数组的定义与使用二维数组的定义与使用字符数组与字符串多维数组 §7.2一维数组7.2.1一维数组的定义1.数组名的确定方法同变量名。2.C语言用方括号[]表示数组元数个数。语法:类型说明符数组名[常量表达式];例:inta[5];floatx[100]; 3.常量表达式为常量和符号常量。不允许有变量,其表达式的值代表了元素的个数。例如:intn=10;floatscore[n];/*错误*/floatscore[5*2];/*正确*/#defineN10floatscore[N];/*正确,N为常量*/ 例:inta[5];表示有5个元素且元素从0开始编排(顺序):a[0],a[1]…,a[4]a[0]014a[1]a[2]a[3]a[4]23a(4)数组中的首元素下标为0,末元素下标为“常量表达式-1”。 7.2.2一维数组的引用2.引用方式:数组名[下标]下标是整型常量或者整型表达式。1.须象使用变量那样,先定义,后使用例:a[0]5+a[1]6为正确的算术表达式注意:对于一维数组,C语言规定,只能逐个引用数组元素而不能一次引用整个数组。 #includemain(){inta[10]={1,2,3,4,5,6,7,8,9,10},j;printf(“%d”,a);for(j=0;j<10;j++)printf(“%d ”,a[j]);}()() 3.一般地,一维数组各元素分配在连续地内存单元之中。下标不能越界。inta[4];a[4]=5;/*下标越过上界*/a[-1]=0;/*下标越过下界*/ 在定义数组的时候对数组元素赋予初始值。只给一部分元素赋予初始值(前一部分),剩余元素的初始值自动为0;7.2.2一维数组的初始化inta[5]={1,2,3,4,5};等价于:a[0]=1;a[1]=2;a[2]=3;a[3]=4;a[4]=5;如inta[5]={6,2,3};等价于:a[0]=6;a[1]=2;a[2]=3;a[3]=0;a[4]=0;如inta[3]={6,2,3,5,1};() (3)赋初值为全部0。(4)可以在定义数组时不指定数组元素的个数,而在赋初值时由初始值的个数确定。7.2.2一维数组的初始化inta[5]={0,0,0,0,0};或者inta[5]={0};不能:inta[5]={0*5};inta[]={1,2,3,4,5,6};编译系统根据初值个数确定数组维数 要注意省略数组长度时候的赋值:intdata[5]={1,2,3};表示数组data中前面三个元素的初始值分别为1,2,3,而后两个元素的值为0。如写成:intdata[]={1,2,3};,则表示数组data的长度为3,三个元素的初始值分别为1,2,3。 例1有十个学生的成绩,求平均分9285687554889845617992856854889845756179a[0]a[1]a[2]a[3]a[4]a[5]a[6]a[7]a[8]a[9]a#includemain(){intk,a[10];for(k=0;k<10;k++)scanf(“%d”,&a[k]);for(k=0;k<10;k++)sum+=a[k];printf(“Averageis%d ”,sum/10);}7.2.3一维数组的程序举例 例2:排序问题–––计算机处理数据的一个重要问题冒泡排序法:排序过程:(1)比较第一个数与第二个数,若为逆序a[0]>a[1],则交换;然后比较第二个数与第三个数;依次类推,直至第n-1个数和第n个数比较为止——第一趟冒泡排序,结果最大的数被安置在最后一个元素位置上(2)对前n-1个数进行第二趟冒泡排序,结果使次大的数被安置在第n-1个元素位置(3)重复上述过程,共经过n-1趟冒泡排序后,排序结束。 例:8,4,20,100,28,1,第2趟:4,8,20,1,28,100第3趟:4,8,1,20,28,100第4趟:4,1,8,20,28,100第5趟:1,4,8,20,28,100第1趟:4,8,20,100,28,14,8,20,100,28,14,8,20,100,28,14,8,20,28,100,14,8,20,28,1,100 程序:#includemain(){inta[10];inti,j,t;printf("pleaseinput10n~: ");for(i=0;i<10;i++)scanf("%d",&a[i]);for(j=0;j<9;j++)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: ");for(i=0;i<10;i++)printf(“%d”,a[i]);}输入排序输出 第七章数组(array)内容提要数组的概念一维数组的定义与使用二维数组的定义与使用字符数组与字符串多维数组 §7.3二维数组7.3.1二维数组的定义1.不可将定义写为inta[4,10]。语法类型说明符数组名[常量表达式][常量表达式]例:inta[4][10];floatx[8][20];行数列数 2.可将二维数组的元素看成为若干个特殊的一维数组。如:intb[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维数组的定义和存放。多维数组元素在内存中的存储顺序为:第一维(最左边)的下标变化最慢,最右边的下标变化最快。即:最右边的下标变化最快。 例如:三维数组intscore[2][3][5];,则各元素在内存中的存储位置从低地址到高地址依次为:score[0][0][0]->score[0][0][1]->score[0][0][2]->score[0][0][3]->score[0][0][4]->score[0][1][0]->score[0][1][1]->score[0][1][2]->score[0][1][3]->score[0][1][4]->score[0][2][0]->score[0][2][1]->score[0][2][2]->score[0][2][3]->score[0][2][4]->score[1][0][0]->score[1][0][1]->score[1][0][2]->score[1][0][3]->score[1][0][4]->score[1][1][0]->score[1][1][1]->score[1][1][2]->score[1][1][3]->score[1][1][4]->score[1][2][0]->score[1][2][1]->score[1][2][2]->score[1][2][3]->score[1][2][4]7.3二维数组的定义与使用 4.初始化:按行给二维数组赋初值:inta[3][4]={{1,2,3,4},{5,6,7,8,},{9,10,11,12,}};可以去掉其中的{}。 可以对部分元素赋初值,但需表达清楚。如:inta[3][4]={{1,2},{3},{8}}。则相当于120030008000可通过赋初值决定数组大小。如为二维,则只可省略第一维的大小.inta[][4]={1,2,3,…,12}; 7.2.2二维数组元素的引用语法:数组名[下标][下标]其中的下标为整型表达式,但不得越界。例如:inta[2][3];a[1][3]=5;/*第2维下标越过上界*/a[-1][2]=0;/*第1维下标越过下界*与一维数组元素一样,二维数组元素相当于同类型的简单变量。 7.3.3程序举例a=123456b=142536程序如下:main(){inta[2][3]={{1,2,3},{4,5,6}};intb[3][2],i,j;例1将一个二维数组行和列元素互换,存到另一个二维数组中。例如: printf("arraya: ");for(i=0;i<=1;i++){for(j=0;j<=2;j++){printf("%5d",a[i][j]);b[j][i]=a[i][j];}printf(" ");}printf("arrayb: ");for(i=0;i<=2;i++) {for(j=0;j<=1;j++)printf("%5d",b[i][j]);printf(" ");}}运行结果如下:arraya:123456 arrayb:142536 例2用二维数组存储矩阵A和B,计算它们的乘积C=A×B。分析:用两个二维数组intA[4][3],B[3][3]分别存储矩阵A4×3和B3×3,它们的乘积存储在二维数组intC[3][3]中。根据矩阵相乘的含义,乘积矩阵C4×3为:,i=I...4,J=1...37.3二维数组的定义与使用 #includevoidmain(void){intA[4][3]={{1,2,3},{4,0,2},{1,1,0},{1,2,1}},B[3][3]={{1,0,1},{0,1,0},{1,0,2}},C[4][3];inti,j,k;for(i=0;i<4;i++)for(j=0;j<3;j++){C[i][j]=0;for(k=0;k<3;k++)C[i][j]+=A[i][k]*B[k][j];}7.3二维数组的定义与使用 /*以下输出乘积矩阵的结果*/for(i=0;i<4;i++){for(j=0;j<3;j++)printf(“%-4d”,C[i][j]);printf(“ ”);}}7.3二维数组的定义与使用 程序运行情况如下:4276081112237.3二维数组的定义与使用 第七章数组(array)内容提要数组的概念一维数组的定义与使用二维数组的定义与使用字符数组与字符串多维数组 §7.4字符数组7.4.1字符数组的定义类型名数组名大小存放字符数据。字符串–––用字符数组存放。charc[10];说明:(1)如果输入的字符数超过10个,则数组只存储前面10个;(2)如果输入的字符中含有空格符,空格符和其它字符一样,算其中一个; (3)如果输入10个字符之前,输入回车符,则回车符也算一个字符;(4)对于字符型变量的输入和输出,可以使用getchar()和putchar()函数。getchar()从键盘读一个字符,并自动把击键结果回应到屏幕上。putchar(ch)将传入的字符ch写在屏幕的当前光标处。二者的函数原型为:intgetchar(void);intputchar(intc);7.4字符数组与字符串 定义一个二维字符数组的形式为:char数组名[常量表达式][常量表达式];例如:charname[5][10];表示数组name是一个二维字符数组,它存储的字符个数为5×10,比如可以让这个数组存储5个学生的姓名,每个学生的姓名假定不超过10个字符。也就是说,我们同样可以把二维字符数组看成是由若干个(此例为5个)一维字符数组构成的。定义二维字符数组后,对字符数组中元素的引用方法也类似于其它类型的数组。7.4字符数组与字符串 1.初始化:直接给出字符串中的各字符chara[4]={'G','o','o','d'};若字符多于元素个数,则语法错,反之,后而补" "可以去掉定义时的大小设置,而通过自动赋值决定长度(大小)charx[]={'I','','a','m','','a','','s','t','u','d','e','n','t'};如果初值中间含有字符’ ’,则以字符串处理时,字符’ ’作为该字符串的结束标记。例如:charname[10]={‘a’,’b’,‘c’,’d’,‘ ’,’f’,‘g’,’h’,‘i’,’j’};printf("%s",name);/*输出为abcd*/ 前面说过,字符串常量用“”表示,且由‘ ’结尾.字符串常量可以用来对字符数组进行赋值。charx[]={“Iamastudent.”};或者charx[]="Iamastudent.";则长度为15+1=16,其中x[15]存放‘ ’,其中{}亦可省略。 2.字符数组的引用每一个字符数组元素相当于一个字符变量#includemain(){charc[10]={'I','','a','m','','a','','b','o','y'};inti;for(i=0;i<10;i++)printf("%c",c[i]);printf(" ");} 格式符:%c–––逐个输入/输出字符。%s–––整个串一次输入/输出。7.4.2字符数组的输入输出1.输入(用%s)输入字符串时,系统自动加上‘ ’hello!‘ ’可以用字符串常量对字符数组进行初始化,用“”作为标记隔开不同字符串例如:charname[10]={“chenjun”};或charname[10]=“chenjun”;(1) 用scanf输入多个字符串,用空格作为标记隔开不同字符串。charstr1[5],str2[5],str3[5];scanf("%s%s%s",str1,str2,str3);实际赋值str1:How str2:are str3:you 则:输入Howareyou?没有用&符号?(2) 输入:Howareyou则只会将How输入,且存为scanf中须用取地址符号;但是,数组名本身就表示它的存储地址,因此不需要&符号。str:How ……另外:charstr[13]scanf("%s",str); 用函数gets(字符数组名),函数gets(字符数组名)gets(str)读输入字符串,用回车键作为字符串的结束标记。如:chars1[80];gets(s1);输入:HuaqiaoUni.(3) 2.输出(用%s)用%s输出时,不输出‘ ’.在printf中须直接写数组名(!!!).charc[]={"Iamastudent"};printf("%s",c); main(){charch[5];inti;for(i=0;i<4;i++){scanf(“%c”,&ch[i]);printf(“%c”,ch[i]);}}main(){charch[5];inti;scanf(“%s”,ch);printf(“%s”,ch);}1.用%c,%s格式输入和输出总结数组名代表该数组的首地址不加入地址符号& main(){charch[]={“student”};}puts(字符数组名)gets(字符数组名)main(){charch[5];gets(ch);puts(ch);}puts(ch);2、字符串输入与输出函数 若数组长度大于字符串长度,则遇到‘ ’即停止输出charc[10]="china";printf("%s",c);输出时遇到第一个‘ ’即结束。charname[10]={‘a’,’b’,‘c’,’d’,‘ ’,’f’,‘g’,’h’,‘i’,’j’};printf("%s",name);/*输出为abcd*/ 字符串处理函数包含在头文件string.h字符串输出函数puts格式:puts(字符数组)功能:向显示器输出字符串(输出完,换行)说明:字符数组必须以‘ ’结束字符串输入函数gets格式:gets(字符数组)功能:从键盘输入一以回车结束的字符串放入字符数组中,并自动加‘ ’说明:输入串长度应小于字符数组维数例#include#includemain(){charstring[80];gets(string);puts(string);}输入:Howareyou?输出:Howareyou?7.3.3字符串处理函数 字符串连接函数strcat格式:strcat(字符数组1,字符数组2)功能:把字符数组2连到字符数组1后面返值:返回字符数组1的首地址说明:字符数组1必须足够大连接前,两串均以‘ ’结束;连接后,串1的‘ ’取消,新串最后加‘ ’字符串拷贝函数strcpy格式:strcpy(字符数组1,字符串2)功能:将字符串2,拷贝到字符数组1中去返值:返回字符数组1的首地址说明:字符数组1必须足够大拷贝时‘ ’一同拷贝不能使用赋值语句为一个字符数组赋值例charstr1[20],str2[20];str1={“Hello!”};()str2=str1;()charstr3[]={“Hello!”};(√) 例strcpy与strcat举例#include#includevoidmain(){chardestination[25];charblank[]="",c[]="C++",turbo[]="Turbo";strcpy(destination,turbo);strcat(destination,blank);strcat(destination,c);printf("%s ",destination);}TurboC++TrboC++0123456789u 24…….Trbo0123456789u 24…….…….Trbo 0123456789u24…….…... 字符串比较函数strcmp格式:strcmp(字符串1,字符串2)功能:比较两个字符串比较规则:对两串从左向右逐个字符比较(ASCII码),直到遇到不同字符或‘ ’为止返值:返回int型整数,a.若字符串1<字符串2,返回负整数b.若字符串1>字符串2,返回正整数c.若字符串1==字符串2,返回零说明:字符串比较不能用“==”,必须用strcmp字符串长度函数strlen格式:strlen(字符数组)功能:计算字符串长度返值:返回字符串实际长度,不包括‘ ’在内例对于以下字符串,strlen(s)的值为:(1)chars[10]={‘A’,‘ ’,‘B’,‘C’,‘ ’,‘D’};(2)chars[]=“tv\ will ”;(3)chars[]=“x69 82 ”;答案:131 #include#includemain(){charstr1[]=”Hello!",str2[]=”Howareyou?”,str[20];intlen1,len2,len3;len1=strlen(str1);len2=strlen(str2);if(strcmp(str1,str2)>0){strcpy(str,str1);strcat(str,str2);}elseif(strcmp(str1,str2)<0){strcpy(str,str2);strcat(str,str1);}elsestrcpy(str,str1);len3=strlen(str);puts(str);printf(”Len1=%d,Len2=%d,Len3=%d ”,len1,len2,len3);}例strcmp与strlen举例Howareyou?Hello!Len1=6,Len2=12,Len3=18 应用举例例输入一行字符,统计其中有多少个单词输入一字符串给stringi=0num=0word=0当((c=string[i])!=‘ ’)c=空格真真假假word=0word=1num=num+1i=i+1输出:numword==0#includemain(){charstring[81];inti,num=0,word=0;charc;gets(string);for(i=0;(c=string[i])!=' ';i++)if(c=='')word=0;elseif(word==0){word=1;num++;}printf("Thereare%dwordsintheline ",num);} 当前字符=空格是否未出现新单词,使word=0,num不累加前一字符为空格(word==0),新单词出现,word=1,num加1前一字符为非空格(word==1),未出现新单词,num不变否0是11是1未01否0是12否1未12是1未02否0是13是1未03否0是14否1未14否1未14否1未14例输入:Iamaboy.当前字符是否空格word原值新单词开始否word新值num值Iamaboy. 第七章数组(array)内容提要数组的概念一维数组的定义与使用二维数组的定义与使用字符数组与字符串多维数组 7.5多维数组C允许多于二维的数组,维数上限仅受编译程序限制。定义多维数组的一般形式为:类型名多维数组名[常量表达式1][常量表达式2][常量表达式3]...[常量表达式n]因为占用内存量较大,所以三维以上的数组并不常用。例如:inta[10][6][9][4];,数组a中每个元素占用2个字节的空间,整个数组需要占用2×10×6×9×4,共4320个字节的存储空间大小。使用多维数组时,计算各维下标占用处理器时间,这样存取多维数组元素的速度要比一维数组元素时慢。其它初始化和使用多维数组的用法,与二维数组类似。7.5多维数组 例7-15编写程序,输入2个班的10个学生的3门课程成绩,计算所有学生成绩的平均值。#includevoidmain(void){intgrade[2][5][2];inti,j,k;longsum=0;doubleaverage=0.0f;7.5多维数组 for(i=0;i<2;i++)/*第1维控制2个班级*/for(j=0;j<5;j++)/*第2维控制5个学生*/for(k=0;k<2;k++){/*第3维控制每个学生的2门课程*/scanf("%d",&grade[i][j][k]);sum+=grade[i][j][k];}average=sum/20.0;printf("average=%f ",average);}7.5多维数组 程序运行情况如下:输入:5060608050607080708050508070606070507080输出:average=65.0000007.5多维数组 习题1:有一个3*4的矩阵,要求写一个程序能找出其中值最大的那个元素,并给出这个元素所在的行号和列号。习题2:编一程序,将两个字符串连接起来,存在一个新的数组中,不要用strcat函数。习题3:自己编写程序,实现折半查找法(又叫二分查找法)。课堂练习 一、二分查找的先决条件表中结点有序,且顺序(一维数组)存储。二、二分法思想:取中,比较(1)求有序表的中间位置mid(2)若r[mid]==k,查找成功;若r[mid]>k,在左子表中继续进行二分查找;若r[mid]r[m]:在右半部分继续查找。i=m+1=4,j=5m=(i+j)/2=4。r[m]==k:查找成功。m=(i+j)/2=6。 1221303538404855566064i=1,j=11,m=(i+j)/2=6。r[m]k:在左半部分继续查找。i=7,j=m-1=8,m=(i+j)/2=7。r[m]k:在左半部分继续查找。i=8,j=m-1=7,i>j:查找失败二分法查找示例(2)k=501234567891011 简单算法描述inti,j,k,flag=0;…...i=0,j=n;while(i<=j){mid=(i+j)/2;//取中if(k==r[mid])printf(“ok ”),flag=1,break;//查找成功elseif(ka[0],再与a[i]比较,…一直比较到x=a[p])&&(p<=m))p++;for(i=m;i>=p;i--)a[i+1]=a[i];a[p]=x;m++;for(i=0;i<=m;i++)printf(“%4d,”,a[i]);}2、实现算法