
第7章c语言(数组与字符串).ppt
57页第7章数组与字符串p 数组概述 p 一维数组 p 二维数组 p 多维数组 p 字符串 p 综合应用——杨辉三角 p 跟我上机 第7章数组与字符串þ 数组概述 p 一维数组 p 二维数组 p 多维数组 p 字符串 p 综合应用——杨辉三角 p 跟我上机 第7章数组与字符串þ 数组概述 þ 一维数组 p 二维数组 p 多维数组 p 字符串 p 综合应用——杨辉三角 p 跟我上机 第7章数组与字符串þ 数组概述 þ 一维数组 þ 二维数组 p 多维数组 p 字符串 p 综合应用——杨辉三角 p 跟我上机 第7章数组与字符串þ 数组概述 þ 一维数组 þ 二维数组 þ 多维数组 p 字符串 p 综合应用——杨辉三角 p 跟我上机 第7章数组与字符串þ 数组概述 þ 一维数组 þ 二维数组 þ 多维数组 þ 字符串 p 综合应用——杨辉三角 p 跟我上机 第7章数组与字符串þ 数组概述 þ 一维数组 þ 二维数组 þ 多维数组 þ 字符串 þ 综合应用——杨辉三角 p 跟我上机 第7章数组与字符串þ 数组概述 þ 一维数组 þ 二维数组 þ 多维数组 þ 字符串 þ 综合应用——杨辉三角 þ 跟我上机 7.1 数组概述 Ø到目前为止,所使用的变量都有一个共同的特点,就是每个变量只能存储一个数值,比如定义三个变量num,money和cname,代码如下:int num;doulbe money;char cname;这三个变量属于不同的数据类型,所以只能一次定义一个变量,如果这三个量属于同一种数据类型,就可以使用数组一起定义多个变量。
7.1 数组概述Ø数组表示的是一组数据类型相同的数,这组数当中的每一个元素都是一个独立变量,数组就是用来存储和处理一组相同类型的数据的序号成绩代码560.5e370b180c490.5d2100a7.2 一维数组Ø7.2.1 一维数组的定义Ø7.2.2 一维数组的初始化Ø7.2.3 一维数组元素的操作Ø7.2.4 数组作为参数传递Ø7.2.5 一维数组的应用举例7.2.1 一维数组的定义Ø一维数组定义的一般形式为:类型说明符 数组名[常量表达式];例如:int code[5];或者#define NUM 5int code[NUM];Ø上述两种形式都正确的定义一个名称code的整型数组,该数组含有5个整型变量,这5个整型变量的下标,依次是:code[0]、code[1]、code[2]、code[3]和code[4]Ø在C语言当中,数组的下标总是从0开始记的,而不是从1开始,这一点大家需要格外注意,特别是最初接触到数组7.2.1 一维数组的定义Ø使用code数组存储上节中建立的数据表中的序号列中的数据,如下表所示 序号数组5code[0]3code[1]1code[2]4code[3]2code[4]53142低地址高地址4个字节7.2.1 一维数组的定义Ø表中数组code中元素code[0]是一个整型变量,它存储的是数据5,它在使用上一般的变量没有区别,比如int x=5,code[0]与x不同的地方只是code[0]采用了数组名和下标组合的形式。
比如下面的代码:printf(“code[0]=%d,code[4]=%d\n”,code[0],code[4]);输出结果是code[0]=5,code[4]=2又如下面的代码:for(int i=0;i<5;i++) printf(“code[%d]=%d\n”,code[i]);输出的结果是code[0]=5code[1]=3code[2]=1code[3]=4code[4]=27.2.1 一维数组的定义1. 数组定义的说明Ø⑴ 数组使用的是方括号[ ],不要误写成小括号( )int name(10);/*是错误的形式*/Ø⑵ 数组命名必须按照命名规则Ø⑶ 数组下标总是从0开始的,以上面定义的code数组为例,数组的元素下标的范围是从0到4,而不是从1到5,大于4的下标会产生数组溢出错误,下标更不能出现负数code[0]/*是存在的,可以正确的访问*/code[4]/*是存在的,可以正确的访问*/code[5]/*是不存在的,无效的访问*/code[-1]/*是错误的形式*/7.2.1 一维数组的定义Ø⑷ 定义数组时,code[5]中括号中的数字5,表示的是数组中元素的总数,使用数组时,code[2]=1中括号中的数值是下标,表示的是使用的数组中哪一个元素。
Ø⑸ 在定义数组元素总数时,如上例中的5或者NUM,在数组的定义时,要求括号中数据一定要是常量,而不能是变量,但是数组定义后,使用该数组的元素时,下标可以是常量,也可以是变量,或者表达式7.2.1 一维数组的定义int number=5;int code[number];/*在编译这样代码时,编译器会报错*/假如code数组已经正确定义,下面的使用是正确的int n = 3;code[n] = 100; /*等价于code[3]=100; */code[n+1]=80; /*等价于code[4]=80; */code[n/2]=65;/*等价于code[1]=65,这个是需要注意的,下标只能是整数,如果是浮点数编译器会舍弃小数位取整数部分*/code[2]=code[1] + n;code[0]=99.56/*等价于code[0]=99,因为code[0]本就是一个整型变量,赋值时数据类型转换,直接把浮点数舍弃小数位后赋值给了code[0]*/7.2.1 一维数组的定义Ø2. 其他类型数组的定义⑴ 整型数组的定义int array[10];/*包含10个整型元素的数组名为array的数组,下标范围从0到9*/⑵ 浮点型数组的定义float score[3];/*包含3个float类型元素的数组名为score的数组,下标范围从0到2*/⑶ 字符型数组的定义char name[5];/*包含5个char类型元素的数组名为name的数组,下标范围从0到4*/7.2.1 一维数组的定义Ø3. 数组的地址数组code的存储区域,在某一个地址中存储了code[0]元素值5,然后地址从低到高,每次增加4个字节(int类型占用4个字节),顺序存储了其他数组元素的值。
假如现在已知code[0]在内存的地址,那么code[1]的地址是多少呢?code[1]的就是在code[0]的地址基础上加4个字节,同理,code[4]的地址就是在code[0]地址的基础上加4个*4字节,共16个字节所以对于数组,只要知道数组的首地址,那么就可以根据偏移量计算出待求数组元素的地址7.2.1 一维数组的定义Ø数组的首地址又怎么得到呢?其实C语言在定义数组时就已经为预先设置好了这个地址,这个预设值就是数组名比如要输出数组的首地址,就可以采用下面的方式printf("code的首地址是%d\n",code);输出结果就是code数组的首地址值,关于地址的更多的使用方法,大家可以参看后续指针章节详细讲解7.2.2 一维数组的初始化Ø1. 先定义数组,再进行初始化如下代码:int code[5];/*定义整型数组,数组有5个元素,下标从0到4*/code[0]=5; /*数组第0个元素赋值*/code[1]=3; /*数组第1个元素赋值*/code[2]=1; /*数组第2个元素赋值*/code[3]=4; /*数组第3个元素赋值*/code[4]=2; /*数组第4个元素赋值*/7.2.2 一维数组的初始化Ø2. 在定义的同时对其初始化int code[5]={5, 3, 1, 4, 2};/*定义整型数组,同时初始化数组的5个元素*/数学当中使用{ }表示的是集合的含义,这里也一样,这对括号就是圈定了这组数组的值,或者省略数组元素个数,如下面的语句:int code[ ]={5, 3, 1, 4, 2};因为{ }中是每个数组元素的初值,初始化也相当告诉了数组中有多少个元素,所以可以省略[ ]中的5。
对于定义数组同时对其初始化,可以省略中括号中数组的个数,但是如果分开写就是错误的,如下面的代码所示7.2.2 一维数组的初始化int code[5]; /*定义数组*/code[5]={5, 3, 1, 4, 2};/*错误的赋值*/或者code[]={5, 3, 1, 4, 2};/*错误的赋值*/上面都是错误的形式int code[];/*错误的数组定义*/code[0]=5; /*错误的赋值*/code[1]=3; /*错误的赋值*/Ø定义数组时没有定义数组元素的个数,使用时就会发生异常,原因是内存中并没有为数组code开辟任何存储空间,数据自然无处存放7.2.2 一维数组的初始化数组初始化时常见的其他情况如下所示Ø⑴ 定义数组时省略[ ]内元素总数int code[10]= {1,2,3,4,5};/*表示code数组共有10个元素,仅对前5个进行了初始化,后面5个元素编译器自动初始化为0*/int code[]= {1,2,3,4,5};/*表示code数组共有5个元素,初始化code[0]=1,code[1]=2,...,code[4]=5*/Ø⑵ 元素初始化为0int code[5]= {0,0,0,0,0};或者int code[5]={0}二者含义相同,都是对5个元素初始化为0,显然第二种方式更为简洁。
7.2.3 一维数组元素的操作int i;int array[5]={1,2,3,4,5}; /*定义数组,同时初始化*/for(i=0;i<5;i++)/*循环访问数组元素*/printf("%d",array[i]);输出结果是1,2,3,4,5此代码中定义array为整型数组,包含5个整型元素,并同时初始元素值,分别是:array[0]=1,array[1]=2,array[2]=1,array[3]=2,array[4]=5for语句中循环变量i初值是0,终值是4,步长是1,调用printf()函数就可以访问到数组array中的每一个元素了Ø注意:变量i的范围是0~4,否则程序会报数组溢出错误7.2.3 一维数组元素的操作Ø【【范例范例7-1】】 一维数组的输入输出一维数组的输入输出01 #include
使用一维数组计算元素的和以及平均值01 #include
例如,主函数中有整型数组定义:int array[5];调用函数的语句如下:findMax(array);这里使用数组名作为参数传递给函数findMax(),实参数据类型需要和形参数据类型一致才可以,所以可以这样定义findMax()函数的参数void findMax(int a[5])或者可以省去数组5,写成下面的形式void findMax(int a[])7.2.4 数组作为参数传递Ø【【范例范例7-3】】 求数组最大值求数组最大值01 #include
这就是说,对于变量,实参可以改变形参,形参的改变不会影响到实参;对于数组,实参可以改变形参,形参的改变也会改变实参7.2.4 数组作为参数传递Ø【范例7-4】 传值和传地址7.2.5 一维数组的应用举例Ø【【范例范例7-5】】 将一个数组逆序输出将一个数组逆序输出01 #include 7.3 二维数组Ø7.3.1 二维数组的定义Ø7.3.2 二维数组的初始化Ø7.3.3 二维数组元素的操作Ø7.3.4 二维维数组的应用举例7.3.1 二维数组的定义Ø二维数组定义的一般形式为类型说明符 数组名[常量表达式][常量表达式]例如:int a[3][4];/*定义a为3行4列的数组*/int b[5][10]; /*b为5×10(5行10列)的数组*/不能写成下面的形式int a[3,4]; /*错误数组定义*/int b[5,10]; /*错误数组定义*/7.3.1 二维数组的定义a[0][0]a[0][1]a[0][2]a[0][3]a[1][0]a[1][1]a[1][2]a[1][3]a[2][0]a[2][1]a[2][2]a[2][3]7.3.1 二维数组的定义Ø已知a[0][0]在内存中的地址,a[1][2]的地址是多少呢,计算方法是如下:a[1][2]的地址 = a[0][0]地址 + 24字节24字节 = (1行*4*列+2列)*4字节Ø还需要注意到数组a[3][4]元素下标的变化范围,行号范围是从0到2,列号范围是0到3, 7.3.2 二维数组的初始化Ø1. 先定义再初始化int a[3][4];a[0][0]=1;a[2][3] = 9;2. 定义同时初始化int a[3][4]= { {1,2,3,4},{5,6,7,8},{9,0,1,2}};或者int a[3][4]= { 1,2,3,4,5,6,7,8,9,0,1,2};已经讲过了,二维数组在内存中是按线性顺序存储的,所以内存括号可以省去,不会产生影响。 还可以这样:int a[ ][4]= { {1,2,3,4},{5,6,7,8},{9,0,1,2}};或者int a[][4]= { 1,2,3,4,5,6,7,8,9,0,1,2};省去3也是可以的,但是4是不能省去的编译器会根据所赋的数值的个数及数组的列数,自动计算出数组的行数7.3.2 二维数组的初始化Ø分析下面的二维数组的初始化后的值int a[3][4]={{1},{5},{9}};可以认为二维数组是由3个一维数组构成的,每个一维数组有4个元素,那就可以和一维数组初始化衔接上了,经过上述初始化,数组a元素的值如下表所表示的形式a[0][0]=1a[0][1]=0a[0][2]=0a[0][3]=0a[1][0]=5a[1][1]=0a[1][2]=0a[1][3]=0a[2][0]=9a[2][1]=0a[2][2]=0a[2][3]=07.3.3 二维数组元素的操作Ø二维数组元素的操作和一维数组元素的操作相似,一般使用双重循环遍历数组的元素,外层循环控制数组的行标,内层循环控制数组的列标,如下所示:int i,j;int array[3][4];for(i=0;i<3;i++){ for(j=0;j<4;j++) { array[i][j]=4*i+j; }}经过上面双循环的初始化操作,数组array[3][4]的元素的值是{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 二维维数组的应用举例Ø【【范例范例7-7】】 求一个求一个3*3矩阵对角线元素之和矩阵对角线元素之和01 #include point数组在内存中仍然是按照线性结构占据连续的存储单元,地址从低到高的顺序如下所示: 7.4 多维数组point[0][0][0]→point[0][0][1]→point[0][0][2]→point[0][0][3]→point[0][1][0]→point[0][1][1]→point[0][1][2]→point[0][1][3]→point[0][2][0]→point[0][2][1]→point[0][2][2]→point[0][2][3]→point[1][0][0]→point[1][0][1]→point[1][0][2]→point[1][0][3]→point[1][1][0]→point[1][1][1]→point[1][1][2]→point[1][1][3]→point[1][2][0]→point[1][2][1]→point[1][2][2]→point[1][2][3]遍历三维数组,通常使用三重循环实现,以point[2][3][4]数组为例说明int i,j,k; /*定义循环变量*/int pointf[2][3][4];/*定义数组*/ for (i=0;i<2;i++) /*循环遍历数组*/ for(j=0;j<3;j++) for(k=0;k<4;k++) printf(“%d”,point[i][j][k]);7.5 字符串Ø字符串是使用双引号包含的字符序列,也把字符串称为字符串常量。 比如下面所示的内容就是字符串Ø“hello world”Ø“123abc,Ø在C语言中,字符串存储成一个指定的以‘\0’作为结束标志的字符串其中‘\0’是转义符比如“hello world”字符串,它并不是像看到的占用了11个存储字节,而是占用了内存中12个字节‘\0’是编译器自动加上的,是字符串的一部分,占用一个存储单元7.5 字符串Ø字符串“hello world”在内存中的存储形式如下图所示helloworld\07.5.1 字符串和字符数组Ø认识了字符串,它和字符数组有着什么的相同和不同点呢?字符数组是由字符构成的数组,它跟之前讲的数组使用方法一样,可以这样定义字符串,如下所示char c[11]={‘h’,’e’,’l’,’l’,’o’,’ ’,’w’,’o’,’r’,’l’,’d’};或者char c[]={‘h’,’e’,’l’,’l’,’o’,’ ’,’w’,’o’,’r’,’l’,’d’};c[0]=’h’;c[11]=’d’;或者先定义数组再进行初始化都是可以的 7.5.1 字符串和字符数组Ø注意到上面提到两个图是不同的,字符所占的字节数是不同的字符串的最后一位字符,是由编译器自动的加上了“\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 字符串和字符数组Ø【范例7-9】 字符串和字符数组01 #include Ø标准输出函数printf和puts函数功能上基本上是完全一样的例如:char c[]="message";/*定义字符数组*/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”按【Enter】键,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 杨辉三角的特点:⑴ 每行数字左右对称,由1开始逐渐变大,然后变小,回到1;⑵ 第n行的数字个数为n个;⑶ 第n行数字和为2n-1;⑷ 每个数字等于上一行的左右两个数字之和如下所示:11 11 2 11 3 3 11 4 6 4 11 5 10 10 5 17.8 跟我上机 Ø⑴ 编写C程序,实现以下功能:有一个3*3的数组,求数组中最大值、最小值、总和和平均值,并输出最大值和最小值所在的位置7.8 跟我上机 Ø⑵ 编写C程序,实现以下功能:某个公司采用公用传递数据,数据是四位的整数,在传递过程中是加密的,加密规则如下:每位数字都加上5,然后用和除以10的余数代替该数字,再将第一位和第四位交换,第二位和第三位交换。












