《第7章c语言(数组与字符串).ppt》由会员分享,可在线阅读,更多相关《第7章c语言(数组与字符串).ppt(57页珍藏版)》请在三一办公上搜索。
1、第7章数组与字符串,数组概述 一维数组 二维数组 多维数组 字符串 综合应用杨辉三角 跟我上机,第7章数组与字符串,数组概述 一维数组 二维数组 多维数组 字符串 综合应用杨辉三角 跟我上机,第7章数组与字符串,数组概述 一维数组 二维数组 多维数组 字符串 综合应用杨辉三角 跟我上机,第7章数组与字符串,数组概述 一维数组 二维数组 多维数组 字符串 综合应用杨辉三角 跟我上机,第7章数组与字符串,数组概述 一维数组 二维数组 多维数组 字符串 综合应用杨辉三角 跟我上机,第7章数组与字符串,数组概述 一维数组 二维数组 多维数组 字符串 综合应用杨辉三角 跟我上机,第7章数组与字符串,数组
2、概述 一维数组 二维数组 多维数组 字符串 综合应用杨辉三角 跟我上机,第7章数组与字符串,数组概述 一维数组 二维数组 多维数组 字符串 综合应用杨辉三角 跟我上机,7.1 数组概述,到目前为止,所使用的变量都有一个共同的特点,就是每个变量只能存储一个数值,比如定义三个变量num,money和cname,代码如下:int num;doulbe money;char cname;这三个变量属于不同的数据类型,所以只能一次定义一个变量,如果这三个量属于同一种数据类型,就可以使用数组一起定义多个变量。,7.1 数组概述,数组表示的是一组数据类型相同的数,这组数当中的每一个元素都是一个独立变量,数组
3、就是用来存储和处理一组相同类型的数据的。,7.2 一维数组,7.2.1 一维数组的定义7.2.2 一维数组的初始化7.2.3 一维数组元素的操作7.2.4 数组作为参数传递7.2.5 一维数组的应用举例,7.2.1 一维数组的定义,一维数组定义的一般形式为:类型说明符 数组名常量表达式;例如:int code5;或者#define NUM 5int codeNUM;上述两种形式都正确的定义一个名称code的整型数组,该数组含有5个整型变量,这5个整型变量的下标,依次是:code0、code1、code2、code3和code4。在C语言当中,数组的下标总是从0开始记的,而不是从1开始,这一点大
4、家需要格外注意,特别是最初接触到数组。,7.2.1 一维数组的定义,使用code数组存储上节中建立的数据表中的序号列中的数据,如下表所示,7.2.1 一维数组的定义,表中数组code中元素code0是一个整型变量,它存储的是数据5,它在使用上一般的变量没有区别,比如int x=5,code0与x不同的地方只是code0采用了数组名和下标组合的形式。比如下面的代码:printf(“code0=%d,code4=%dn”,code0,code4);输出结果是code0=5,code4=2又如下面的代码:for(int i=0;i5;i+)printf(“code%d=%dn”,codei);输出的
5、结果是code0=5code1=3code2=1code3=4code4=2,7.2.1 一维数组的定义,1.数组定义的说明 数组使用的是方括号,不要误写成小括号()。int name(10);/*是错误的形式*/数组命名必须按照命名规则。数组下标总是从0开始的,以上面定义的code数组为例,数组的元素下标的范围是从0到4,而不是从1到5,大于4的下标会产生数组溢出错误,下标更不能出现负数。code0/*是存在的,可以正确的访问*/code4/*是存在的,可以正确的访问*/code5/*是不存在的,无效的访问*/code-1/*是错误的形式*/,7.2.1 一维数组的定义,定义数组时,code
6、5中括号中的数字5,表示的是数组中元素的总数,使用数组时,code2=1中括号中的数值是下标,表示的是使用的数组中哪一个元素。在定义数组元素总数时,如上例中的5或者NUM,在数组的定义时,要求括号中数据一定要是常量,而不能是变量,但是数组定义后,使用该数组的元素时,下标可以是常量,也可以是变量,或者表达式。,7.2.1 一维数组的定义,int number=5;int codenumber;/*在编译这样代码时,编译器会报错*/假如code数组已经正确定义,下面的使用是正确的int n=3;coden=100;/*等价于code3=100;*/coden+1=80;/*等价于code4=80;
7、*/coden/2=65;/*等价于code1=65,这个是需要注意的,下标只能是整数,如果是浮点数编译器会舍弃小数位取整数部分*/code2=code1+n;code0=99.56/*等价于code0=99,因为code0本就是一个整型变量,赋值时数据类型转换,直接把浮点数舍弃小数位后赋值给了code0*/,7.2.1 一维数组的定义,2.其他类型数组的定义 整型数组的定义int array10;/*包含10个整型元素的数组名为array的数组,下标范围从0到9*/浮点型数组的定义float score3;/*包含3个float类型元素的数组名为score的数组,下标范围从0到2*/字符型数
8、组的定义char name5;/*包含5个char类型元素的数组名为name的数组,下标范围从0到4*/,7.2.1 一维数组的定义,3.数组的地址数组code的存储区域,在某一个地址中存储了code0元素值5,然后地址从低到高,每次增加4个字节(int类型占用4个字节),顺序存储了其他数组元素的值。假如现在已知code0在内存的地址,那么code1的地址是多少呢?code1的就是在code0的地址基础上加4个字节,同理,code4的地址就是在code0地址的基础上加4个*4字节,共16个字节。所以对于数组,只要知道数组的首地址,那么就可以根据偏移量计算出待求数组元素的地址。,7.2.1 一维
9、数组的定义,数组的首地址又怎么得到呢?其实C语言在定义数组时就已经为预先设置好了这个地址,这个预设值就是数组名。比如要输出数组的首地址,就可以采用下面的方式。printf(code的首地址是%dn,code);输出结果就是code数组的首地址值,关于地址的更多的使用方法,大家可以参看后续指针章节详细讲解。,7.2.2 一维数组的初始化,1.先定义数组,再进行初始化如下代码:int code5;/*定义整型数组,数组有5个元素,下标从0到4*/code0=5;/*数组第0个元素赋值*/code1=3;/*数组第1个元素赋值*/code2=1;/*数组第2个元素赋值*/code3=4;/*数组第3
10、个元素赋值*/code4=2;/*数组第4个元素赋值*/,7.2.2 一维数组的初始化,2.在定义的同时对其初始化int code5=5,3,1,4,2;/*定义整型数组,同时初始化数组的5个元素*/数学当中使用 表示的是集合的含义,这里也一样,这对括号就是圈定了这组数组的值,或者省略数组元素个数,如下面的语句:int code=5,3,1,4,2;因为 中是每个数组元素的初值,初始化也相当告诉了数组中有多少个元素,所以可以省略 中的5。对于定义数组同时对其初始化,可以省略中括号中数组的个数,但是如果分开写就是错误的,如下面的代码所示。,7.2.2 一维数组的初始化,int code5;/*定
11、义数组*/code5=5,3,1,4,2;/*错误的赋值*/或者code=5,3,1,4,2;/*错误的赋值*/上面都是错误的形式。int code;/*错误的数组定义*/code0=5;/*错误的赋值*/code1=3;/*错误的赋值*/定义数组时没有定义数组元素的个数,使用时就会发生异常,原因是内存中并没有为数组code开辟任何存储空间,数据自然无处存放。,7.2.2 一维数组的初始化,数组初始化时常见的其他情况如下所示。定义数组时省略 内元素总数int code10=1,2,3,4,5;/*表示code数组共有10个元素,仅对前5个进行了初始化,后面5个元素编译器自动初始化为0*/int
12、 code=1,2,3,4,5;/*表示code数组共有5个元素,初始化code0=1,code1=2,.,code4=5*/元素初始化为0int code5=0,0,0,0,0;或者int code5=0二者含义相同,都是对5个元素初始化为0,显然第二种方式更为简洁。,7.2.3 一维数组元素的操作,int i;int array5=1,2,3,4,5;/*定义数组,同时初始化*/for(i=0;i5;i+)/*循环访问数组元素*/printf(%d,arrayi);输出结果是1,2,3,4,5此代码中定义array为整型数组,包含5个整型元素,并同时初始元素值,分别是:array0=1,a
13、rray1=2,array2=1,array3=2,array4=5for语句中循环变量i初值是0,终值是4,步长是1,调用printf()函数就可以访问到数组array中的每一个元素了。注意:变量i的范围是04,否则程序会报数组溢出错误。,7.2.3 一维数组元素的操作,【范例7-1】一维数组的输入输出。01#include 02#define MAXGRADES 5/*数组元素总数*/03 int main(void)04 05 int codeMAXGRADES;/*定义数组*/06 int i;07/*输入数据*/08 for(i=0;i MAXGRADES;i+);/*循环遍历数组*
14、/09 10 printf(输入一个数据:);11 scanf(%d,17,7.2.3 一维数组元素的操作,【范例7-2】使用一维数组计算元素的和以及平均值。01#include 02#define MAX 5/*数组元素总数*/03 int main()04 05 int codeMAX;/*定义数组*/06 int i,total=0;07 for(i=0;i MAX;i+)/*输入数组元素*/08 09 printf(输入一个数据:);10 scanf(%d,19,7.2.4 数组作为参数传递,如何把数组作为参数传递给函数?可以使用数组名作为参数进行传递。例如,主函数中有整型数组定义:i
15、nt array5;调用函数的语句如下:findMax(array);这里使用数组名作为参数传递给函数findMax(),实参数据类型需要和形参数据类型一致才可以,所以可以这样定义findMax()函数的参数。void findMax(int a5)或者可以省去数组5,写成下面的形式void findMax(int a),7.2.4 数组作为参数传递,【范例7-3】求数组最大值。01#include 02#define MAXELS 503 void findMax(int MAXELS);/*定义函数*/04 int main()05 06 int numsMAXELS=2,18,1,27,
16、16;/*数组初始化*/07 findMax(nums);08 return 0;09 10 void findMax(int valsMAXELS)/*查找最大值函数*/11 12 int i,max=vals0;13 for(i=1;i MAXELS;i+)14 if(max valsi)15 max=valsi;16 printf(The maximum value is%dn,max);17,7.2.4 数组作为参数传递,提 示:调用函数时,变量是按照传值方式传递的,而数组是按照传地址方式传递的。这就是说,对于变量,实参可以改变形参,形参的改变不会影响到实参;对于数组,实参可以改变形参
17、,形参的改变也会改变实参。,7.2.4 数组作为参数传递,【范例7-4】传值和传地址。,7.2.5 一维数组的应用举例,【范例7-5】将一个数组逆序输出01#include 02#define N 503 int main(void)04 05 int aN=9,6,5,4,1,i,temp;/*定义数组*/06 printf(原数组:n);07 for(i=0;iN;i+)/*输入元素*/08 printf(%4d,ai);09 for(i=0;iN/2;i+)/*交换数组元素*/10 11 temp=ai;12 ai=aN-i-1;13 aN-i-1=temp;14 15 printf(n
18、排序后数组:n);16 for(i=0;iN;i+)/*输出元素*/17 printf(%4d,ai);/*输出格式元素占4列*/18 printf(n);19 return 0;20,7.2.5 一维数组的应用举例,【范例7-6】输出100内的素数。,7.3 二维数组,7.3.1 二维数组的定义7.3.2 二维数组的初始化7.3.3 二维数组元素的操作7.3.4 二维维数组的应用举例,7.3.1 二维数组的定义,二维数组定义的一般形式为类型说明符 数组名常量表达式常量表达式例如:int a34;/*定义a为3行4列的数组*/int b510;/*b为510(5行10列)的数组*/不能写成下面
19、的形式int a3,4;/*错误数组定义*/int b5,10;/*错误数组定义*/,7.3.1 二维数组的定义,7.3.1 二维数组的定义,已知a00在内存中的地址,a12的地址是多少呢,计算方法是如下:a12的地址=a00地址+24字节24字节=(1行*4*列+2列)*4字节还需要注意到数组a34元素下标的变化范围,行号范围是从0到2,列号范围是0到3,,7.3.2 二维数组的初始化,1.先定义再初始化int a34;a00=1;a23=9;2.定义同时初始化int a34=1,2,3,4,5,6,7,8,9,0,1,2;或者int a34=1,2,3,4,5,6,7,8,9,0,1,2;
20、已经讲过了,二维数组在内存中是按线性顺序存储的,所以内存括号可以省去,不会产生影响。还可以这样:int a 4=1,2,3,4,5,6,7,8,9,0,1,2;或者int a4=1,2,3,4,5,6,7,8,9,0,1,2;省去3也是可以的,但是4是不能省去的。编译器会根据所赋的数值的个数及数组的列数,自动计算出数组的行数。,7.3.2 二维数组的初始化,分析下面的二维数组的初始化后的值int a34=1,5,9;可以认为二维数组是由3个一维数组构成的,每个一维数组有4个元素,那就可以和一维数组初始化衔接上了,经过上述初始化,数组a元素的值如下表所表示的形式。,7.3.3 二维数组元素的操作
21、,二维数组元素的操作和一维数组元素的操作相似,一般使用双重循环遍历数组的元素,外层循环控制数组的行标,内层循环控制数组的列标,如下所示:int i,j;int array34;for(i=0;i3;i+)for(j=0;j4;j+)arrayij=4*i+j;经过上面双循环的初始化操作,数组array34的元素的值是0,1,2,3,4,5,6,7,8,9,10,11原因是4*i+j,i表示行号,j表示列号,首先赋值i=0的行的数组元素值是0,1,2,3,然后内层循环结束,接下来外层循环变量i=1,继续对数组元素赋值4,5,6,7,这样反复进行,就会得到上面的元素值。,7.3.4 二维维数组的应
22、用举例,【范例7-7】求一个3*3矩阵对角线元素之和。01#include 02 int main()03 04 float a33,sum=0;05 int i,j;06 printf(请输入3*3个元素:n);07 for(i=0;i3;i+)/*循环输入9个元素*/08 09 for(j=0;j3;j+)10 scanf(%f,16,7.3.4 二维维数组的应用举例,【范例7-8】将一个二维数组行和列元素互换,存到另一个二维数组中。01#include 02 int main(void)03 04 int a23=1,2,3,4,5,6;/*数组a*/05 int b32,i,j;06
23、printf(array a:n);07 for(i=0;i=1;i+)08 09 for(j=0;j=2;j+)10 11 printf(%5d,aij);/*输出数组a*/12 bji=aij;/*行列互换存储到数组b*/13 14 printf(n);15 16 printf(array b:n);17 for(i=0;i=2;i+)/*输出数组b*/18 19 for(j=0;j=1;j+)20 printf(%5d,bij);21 printf(n);22 23 return 0;24,7.4 多维数组,例如定义一个三维数组:int point234;三维数组point共有2*3*4
24、=24个元素组成,其中多维数组靠左边维变化速度最慢,靠右边维变化速度最快,从左至右逐渐增加。point数组在内存中仍然是按照线性结构占据连续的存储单元,地址从低到高的顺序如下所示:,7.4 多维数组,point000point001point002point003point010point011point012point013point020point021point022point023point100point101point102point103point110point111point112point113point120point121point122point123遍历三维数组,通
25、常使用三重循环实现,以point234数组为例说明。int i,j,k;/*定义循环变量*/int pointf234;/*定义数组*/for(i=0;i2;i+)/*循环遍历数组*/for(j=0;j3;j+)for(k=0;k4;k+)printf(“%d”,pointijk);,7.5 字符串,字符串是使用双引号包含的字符序列,也把字符串称为字符串常量。比如下面所示的内容就是字符串。“hello world”“123abc,。?”在C语言中,字符串存储成一个指定的以0作为结束标志的字符串。其中0是转义符。比如“hello world”字符串,它并不是像看到的占用了11个存储字节,而是占用
26、了内存中12个字节。0是编译器自动加上的,是字符串的一部分,占用一个存储单元。,7.5 字符串,字符串“hello world”在内存中的存储形式如下图所示。,7.5.1 字符串和字符数组,认识了字符串,它和字符数组有着什么的相同和不同点呢?字符数组是由字符构成的数组,它跟之前讲的数组使用方法一样,可以这样定义字符串,如下所示char c11=h,e,l,l,o,w,o,r,l,d;或者char c=h,e,l,l,o,w,o,r,l,d;c0=h;c11=d;或者先定义数组再进行初始化都是可以的。,7.5.1 字符串和字符数组,注意到上面提到两个图是不同的,字符所占的字节数是不同的。字符串的
27、最后一位字符,是由编译器自动的加上了“0”,而字符数组没有被添加。字符串的长度是12,而字符数组的长度是11,当然也可以设置字符数组的长度是12,如下所示:char c=h,e,l,l,o,w,o,r,l,d,0;正如上面提到的例子,字符串和字符数组在很多时候是可混用的。下面仍然是初始化字符串,换一种方式,不再按照数组赋值方法,对数组元素一个个赋值,而是使用一次性初始化的方法。char c=“hello world”;/*使用双引号*/或者char c=“hello world”;/*等效方法,可以省去大括号*/还是可以按照字符数组的方式对字符串进行操作。,7.5.1 字符串和字符数组,【范例
28、7-9】字符串和字符数组01#include 02 int main()03 04 char c=abc;/*初始化字符串*/05 printf(%sn,c);/*输出字符串*/06 printf(%cn,c0);/*输出c0字符*/07 c1=w;/*修改c1字符为w*/08 printf(%sn,c);09 return 0;10,7.5.2 字符串的输入输出,在第6章中,已经学习了字符串输入输出函数gets()和puts(),此处比较一下它们与scanf()和printf()的异同。标准输出函数printf和puts函数功能上基本上是完全一样的。例如:char c=message;/*定
29、义字符数组*/printf(%s,c);/*输出结果是“message”,没有换行*/puts(c);/*输出结果是“message”,并换行*/可以得出当puts()函数在遇到0时,就会被替换为n,实现换行的作用。除此以外,二者没有什么区别。,7.5.2 字符串的输入输出,标准输出函数scanf和gets函数就有些不大相同了,比如scanf(“%s”,c);/*输入“message”按【Enter】键,C中内容为“message”*/scanf(“%s”,c);/*输入“hello world”按【Enter】键,C中内容为“hello”*/gets(c);/*输入“message”按【En
30、ter】键,C中内容为“message”*/gets(c);/*输入“hello world”按【Enter】键,C中内容为“hello world”*/输入“message”,C中接收的内容一致,而输入“hello world”,接收的内容不同,原因是什么呢?scanf函数读取一组字符,直到遇到一个空格或者一个换行字符为止;而gets函数只在一个换行符被检测到才停止接收字符。另外需要注意到,使用scanf函数时,参数“c”前面没有写取地址运算符&符号。,7.5.2 字符串的输入输出,【范例7-10】字符串输入输出函数01#include 02#define MSIZE 8103 int ma
31、in()04 05 char messageMSIZE;06 printf(输入字符串:n);07 gets(message);/*使用gets函数*/08 printf(输出字符串:n);09 puts(message);10 printf(输入字符串:n);11 scanf(%s,message);/*使用scanf函数*/12 printf(输出字符串:n);13 puts(message);14 return 0;15,7.5.3 字符串应用举例,【范例7-11】连接两个字符串,7.5.3 字符串应用举例,【范例7-12】两个字符串复制程序。,7.6 综合应用杨辉三角,【范例7-13】
32、编写代码实现杨辉三角存储到数组中,然后使用循环输出杨辉三角。杨辉三角的特点:每行数字左右对称,由1开始逐渐变大,然后变小,回到1;第n行的数字个数为n个;第n行数字和为2n-1;每个数字等于上一行的左右两个数字之和。如下所示:11 11 2 11 3 3 11 4 6 4 11 5 10 10 5 1,7.8 跟我上机,编写C程序,实现以下功能:有一个3*3的数组,求数组中最大值、最小值、总和和平均值,并输出最大值和最小值所在的位置。,7.8 跟我上机,编写C程序,实现以下功能:某个公司采用公用电话传递数据,数据是四位的整数,在传递过程中是加密的,加密规则如下:每位数字都加上5,然后用和除以10的余数代替该数字,再将第一位和第四位交换,第二位和第三位交换。,