模块3数组与字符串.ppt_第1页
模块3数组与字符串.ppt_第2页
模块3数组与字符串.ppt_第3页
模块3数组与字符串.ppt_第4页
模块3数组与字符串.ppt_第5页
已阅读5页,还剩190页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、实用C语言程序设计教程李金祥 顾小晶 主编,Visual C+,模块3 数组与字符串,任务1 一维数组 学习目标 了解一维数组基本概念、掌握数组类型变量的定义与引用、掌握数组元素的引用,领会一维数组元素的查找、排序、删除、修改和统计等算法。,案例一竞赛成绩的录入和输出 1.问题描述 录入10名学生的计算机语言C的竞赛成绩并输出。,1.1.1案例讲解,2. 编程分析 一维数组中的数组元素是排成一行的一组下标变量,用一个统一的数组名来标识,用下标来指示其在数组中的具体位置。下标从0开始排列。 一维数组通常是和一重循环相配合,对数组元素依次进行处理。,3. 编写源程序 /* EX3_1.C */ #

2、include main( ) int a10,i; printf(请输入十个数:n); for(i=0;i10;i+) scanf(%d, ,4. 运行结果 图3-1案例1运行结果,5. 归纳分析 数组是一些具有相同数据类型的数组元素的有序集合。数组中的每一个元素(即每个成员、也可称为下标变量)具有同一个名称,不同的下标,每个数组元素可以作为单个变量来使用。在数组元素引用时应注意以下几点: (1)引用时只能对数组中元素引用,而不能对整个数组引用。如【EX3_1】中的a。 (2)在引用数组元素时,下标可以是整型常数、已赋值的变量或含变量的表达式。如【EX3_1】中ai的下标i就是已赋值的变量。

3、 (3)由于数组元素本身可看作同一类型的单个变量,因此,对变量的各种操作也都适用于数组元,素。如例【EX3_1】中对数组元素ai的赋值操作和输出操作 (4)引用数组元素时,下标上限(即最大值)不能超界。也就是说,若数组含有n个元素,下标的最大值为n-1,(因下标从0开始);若超出界限,C编译程序并不给出错误信息(即其不检查数组是否超界),程序仍可以运行,但可能会改变该数组以外其它变量或其它数组元素的值,由此会造成不正确的结果。如【EX3_1】,若误将第一个for语句中的i10写成i=10,就会出现下标超界现象。,案例二竞赛成绩的计算 1问题描述 已录入10名学生的计算机语言C的竞赛成绩,计算竞

4、赛成绩的最高分,最低分和平均分。,2编程分析 先假设最高分和最低分初值为第1个学生的成绩,然后比较10次,如果有比当前最高分还大的元素,它就替代当前最高分,如果有比当前最低分还小的元素,它就替代当前最低分。并累加各元素的值,最后输出结果。,3编写源程序 /* EX3_2.C */ #include main( ) int arr10= 90,88,86,84,82,80,78,76,74,72; /*为了简单起见用初始化*/ int i,sum,max,min; sum=0; max=min=arr0;/*最高分最低分初值为第0个元素*/ for(i=0;i10;i+), if (arrima

5、x) max=arri; /*如果有比当前最高分还大的元素,它就替代当前最高分*/ if (arrimin) min=arri; /* 如果有比当前低分还小的元素,它就替代当前低分*/ sum+=arri;/*累加各元素的值 */ printf(最高分=%d 最低分=%d 平均分 =%dn,max,min,sum/10); ,4运行结果如图3-2所示。 图3-2案例2运行结果,5归纳分析 数组元素是从arr0到arr9,千万不要试图使用for(i=1;i=10;i+),因为这样会引用arr10,而这个元素是不存在的。,案例三竞赛成绩的排序 1问题描述 对已知的10个学生的计算机语言C的竞赛成绩

6、从小到大排序,并把排序好的成绩输出。,2编程分析 选择法排序是从待排序数列中,每次选出一个最小的数,和相应位置上的元素交换。第一次选最小的元素放到第一个位置,第二次选次小的元素放到第二个位置,如此类推就能产生一个有序序列。,3编写源程序 /* EX3_3.C */ #include #define NUMBER 10/*定义数列元素个数*/ #include void main( ) int arrayNUMBER=90,88,86,84,82,80,78,76,74,72;/*初始化数组*/ int i,j,k,temp;,printf(排序前数组n); for(i=0;iNUMBER;i+

7、) printf(%3d,arrayi);/*打印排序前数组*/ for(i=0;iNUMBER;i+) /*第i次排序*/ k=i; /*记录当前位置的下标。第一次选择排序时,k=0,当前位置是array0*/ for(j=i+1;jNUMBER;j+) if( arrayj arrayk) k=j; /*某次排序时,如果有任何一个值arrayj小于当前位置值 arrayk,则k下标指定这个j,arrayk仍是这次排序中的最小值*/ if(i!=k), temp=arrayi; arrayi=arrayk; arrayk=temp;/*若最小值不在位置i,则交换arrayi和 arrayk,

8、交换前arrayk是本次排序中的最小元素,arrayi是当前比较位置*/ printf(n输出排序后结果n); for(i=0;iNUMBER;i+) printf(%3d,arrayi);/*输出排序后结果*/ getch( ); ,4运行结果 图3-3 案例3运行结果,5归纳分析 如果待排序数列存放在数组array中,那么:第一次排序时,先假定最小的数是array0。然后将它依次和第1个元素到第NUMBER-1个元素比较,找出它们中的最小值。将最小值和array0交换。如果array0本身最小就不用交换。第二次排序时,array0已经是最小值了,所以这次找出次小值。取出第2到第NUMBER

9、-1个元素中最小值和array1交换。这时array1上是次小值第三次排序就是取出第3个到第NUMBER-1个元素中的最小值和array2交换。,array2是第三小值。排序过程如下。粗斜体字表示本次排序中参于交换的两个数。,案例四新队员招录 1问题描述 对已知的10个学生的计算机语言C的竞赛成绩从小到大排序,并把排序好的成绩输出。,2编程分析 为了把一个数按大小插入已排好序的数组中,则可把欲插入的数与数组中各数逐个比较,当找到第一个比插入数小的元素i时,该元素之前即为插入位置。然后从数组最后一个元素开始到该元素为止,逐个后移一个单元。最后把插入数赋予元素i即可。如果被插入数比所有的元素值都小

10、则插入最后位置。,3编写源程序 /* EX3_4.C */ #include void main( ) int i,j,p,s; float a11=2.07f,2.03f,1.96f,1.94f,1.85f,1.78f,1.76f,1.70f,1.69f,1.68f,q,n; for(i=0;i10;i+) p=i;,q=ai; for(j=i+1;j10;j+) if(qaj) p=j; q=aj; if(p!=i) s=ai; ai=ap; ap=s; ,printf(%8.2f ,ai); printf(n输入新招录队员的身高n); scanf(%f, ,ai=n; printf(n重

11、新排好序的队员按身高由高到低输出n); for(i=0;i=10;i+) printf(%8.2f ,ai); printf(n); ,4运行结果如图3-4所示。 图3-4案例4运行结果 5归纳分析 本程序首先对数组a中的10个数从大到小排序并,输出排序结果。然后输入要插入的整数n。再用一个for语句把n和数组元素逐个比较,如果发现有nai时,则由一个内循环把i以下各元素值顺次后移一个单元。后移应从后向前进行(从a9开始到ai为止)。 后移结束跳出外循环。插入点为i,把n赋予ai即可。 如所有的元素均大于被插入数,则并未进行过后移工作。此时i=10,结果是把n赋于a10。最后一个循环输出插入数

12、后的数组各元素值。 程序运行时,输入数1.77。从结果中可以看出1.77已插入到1.78和1.76之间。,1一维数组的的引入 我们先看一个例子,理解引入数组的必要性。此例需要编程读入一系列学生的成绩,然后求最高分,最低分。首先写一串语句读入学生成绩,放到一系列变量中: printf(“请输入成绩一n”); scanf(“%d”,3.1.2 基础理论,然后是求最高分最低分的过程,只要写一系列的if语句,比较输入的成绩值: if(grade1grade2) if(grade1grade3) . 只要有足够的耐心,最终会得出最高成绩和最低成绩。如果有10个学生的成绩需要处理,if 语句的个数和输入输

13、出语句的个数必然超过十句。程序即使正确也非常复杂。我们如果用数组,情况就将不同。,在C语言中,我们可以定义一个名叫grades的变量,它不代表一个单一的成绩值,而是代表整个成绩组。组中的每一个元素都可以由一个被称为索引或者下标的数字来标明。在数学概念里,下标变量xi是指集合x的i个元素,在C语言中,等价表示为xi。同样grades5表示在grades的数组里的第五号元素。 单独数组元素的使用方法和任何正常变量一样。比如我们可以将一个数组元素值赋给另一个变量:,myg=grades50 这一语句将grades数组中下标为50的元素的值赋给变量myg。如果再一般化一点,i是一个整型变量,那么语句

14、myg=gradesi; 将数组中的第i号元素赋给myg。 数组元素当然也可以放在等号左边。比如 gradesi=myg;把myg的值存入到元素gradesi。,用单一的数组代表有关数据项集合,使我们能开发简明而有效的程序。例如通过改变下标变量的值,我们可以非常容易地访问数组中所有元素。一组学生成绩可以用下面的语句来输入: for(i=0;i100;i+) printf(“请输入第%d个成绩:”,i); scanf(“%d”, ,如果要求出所有学生的总成绩可以这样写: for(i=0;i100;i+) sum=sum+gradesi; 这段代码顺序访问grades数组的前100个元素(0-99

15、),并将每个元素值加到sum中。如果sum的初值为0,循环结束后sum中存放的就是前100个数组元素之和。 由此可见,使用数组大大简化了处理同一数据集合的程序。下面将介绍数组的具体使用方法。,数组是一些具有相同数据类型的数组元素的有序集合。数组中的每一个元素(即每个成员、也可称为下标变量)具有同一个名称,不同的下标,每个数组元素可以作为单个变量来使用。 数组可分为一维数组和多维数组(如二维数组、三维数组)。数组的维数取决于数组元素的下标个数,即一维数组的每一个元素只有一个下标,二维数组的每一个元素均有二个下标,三维数组的每一个元素都有三个下标,以此类推。,2.一维数组的说明、引用 (1)一维数

16、组的定义 在C语言中,变量必须先定义,后使用。数组也是如此,使用数组时必须先定义,后引用。 定义一维数组的一般形式为: 类型标识符 数组名常量表达式; 其中类型标识符是数组中数组元素的数据类型。,数组名是用户定义的数组标识符。方括号中的常量表达式表示数据元素的个数,也称为数组的长度。 例如: int a10; 说明整型数组a,有10个元素。 float b10,c20; 说明实型数组b,有10个元素,实型数组c,有20个元素。 char ch20; 说明字符数组ch,有2个元素。,(2)一维数组元素的引用 数组不能整体使用,只能逐个引用数组元素。 数组元素的一般引用形式为: 数组名 下标 下标

17、可以是整型常数、整型变量和整型表达式,其起始值为0。例如a2+1表示数组a中的第四个元素,ai+j表示数组a中的第i+j+1个元素(i和j为整型变量)。在引用时应注意下标的值不要超过数组的范围。数组的下标的最大值为数组的长度-1。,3. 一维数组的初始化 所谓数组的初始化,就是指在定义数组的同时对数组的各个元素赋初值。 (1)全部元素的初始化 格式:数据类型 数组名数组长度=数组元素值表 “数组元素值表”是用逗号分隔的各数组元素的初值。 例如:,int a6=10,20,30,40,50,60;表示a数组共有6个数组元素。 float r =12.5,-3.11,8.6;表示r数组共有3个实型

18、元素。 (2)部分元素的初始化 格式:数据类型 数组名数组长度=数组部分元素值表 例如: int b10=1,2,3;表示b数组共有3个整型元素。,(3)一维数组的存储 任何一个一维数组在内存中都占用一段连续的空间,依次存储它的各元素的值。元素占用的字节数由数组的数据类型决定。例如int型数组a的每个元素占2字节,6个元素占12个字节。,上述数组a的存储情况如图3-5所示 图3-5 数组a的存储情况,我们通过一个实例来说明数组的存放形式和使用方法。如果有语句序列: int values10; values0=197; values2=-100; values5=350; values3= va

19、lues0+ values5; values9= values5/10; - values2; 语句执行后,数组values 的存储情况如表3-1,表3-1 数组values 执行代码前后的内容,从这段程序可以看出: 数组元素和普通变量一样能使用单目运算符;说明一个数组后,如果不初始化,数组元素的值是随机值,存取未经初始化的数组元素是没有意义的。比如存取values1就没有意义。,【实验3.1.1】对已知的十个元素,求其最大元素,并把最大元素和位置输出。 (1)编程分析 假设首元素为最大值元素,用max标识。 将其余元素依次与max比较,并将大值保 存在max中,将大值元素下标保存在m中。 输

20、出max和m。,3.1.3 技能训练,(2)编写源程序 /*EX3_5.C*/ #include stdio.h #define N 10 void main( ) int aN=20,9,10,-16,-9,18,96,7,11,33; int i,max=a0,m=0; for(i=1;iN;i+) if(maxai), max=ai; m=i; printf(max=%d,为第%d个元素n,max,m+1); (3)在VC+集成环境中输入上述程序,文件存成EX3_5.C。如图3-6所示。 图3-6 运行结果,【实验3.1.2】定义一个长度是20的一维数组b,依次对a进行扫描,将负数在b中

21、由前到后存储,将其他数据在b中由后向前存储。最终b存储的是分类后的数据。 (1)编程分析 定义一个长度为20的一维数组a。 用键盘向一维数组输入20个整数,并依次输出这20个数据。 对数据分类。 输出分类后的数据。,(2)编写源程序 /*EX3_6.C*/ #include stdio.h #define N 20 void main( ) int aN,bN,i,j=0,k=N-1; printf(请输入数据:n); for(i=0;iN;i+) scanf(%d,for(i=0;iN;i+) printf(%d ,ai); if(ai0) bj+=ai; /* 将负数放在b的前部 */ e

22、lse bk-=ai; /* 将其他数放在b的后部 */ printf(n); for(i=0;iN;i+) printf(%d ,bi); ,(3)在VC+集成环境中输入上述程序,文件存成EX3_6.C.如图3-7所示。 调试程序时通常先将N定义为一个小数值,当程序调试成功后再将N定义为常数20,这样可以提高程序的调试效率 在设计调试用数据时,应考虑各种数据情况,以便提高程序的可靠性。 图3-7 运行结果,【练习】有15个数按由小到大顺序存放在一个数组中,输入一个数,要求用折半查找法找出该数是数组中第几个元素的值。如果该数不在数组中,则打印出“无此数”。,3.1.4 拓展与练习,(1)编程分

23、析 折半查找是一种高效的查找方法,它必须在一个有序的数列中进行,基本原理如下:设数列已升序排序,存储在数组a中,对在查找范围内的数据设置3个特殊点,首位置为top,末位置为bot,中间位置为mid=(top+bot)/2,查找过程为: 比较x与amid,若x=amid,查找成功,结束;否则,若xamid,则top=mid+1;若xamid,则bot=mid-1。,若topbot,则查找失败,结束;否则转。 如下是在数列3,6,7,8,21,23,36,38,67,69,80,82,85,88,96中查找69时,top、bot、mid的变化情况: 图3-8折半查找法,(2)编写源程序 /*EX3

24、_7.C*/ #include stdio.h #define N 15 main( ) int aN,i,x,top,bot,mid; printf(输入从小到大排好序的15个数 ); for(i=0;iN;i+) /* 建立升序数组a,用于折半查找* / scanf(%d, /* 输入要查找的数值 */,top=0; /* 设置初始查找边界* / bot=N-1; do mid=(top+bot)/2; /* 确定中间位置 */ if(amid=x) break; /* 找到x 后终止循环 */ else if(amidx) top=mid+1; /* 确定后半段为下一次查找的范围 */

25、else bot=mid-1; /* 确定前半段为下一次查找的范围 */,(3)在VC+集成环境中输入上述程序,文件存成EX3_7.如图3-9所示。 图3-9 运行结果,1编程规范 (1)数组名的书写规则应符合标识符的书写规定。数组名不能与其它变量名相同。,3.1.5 编程规范与常见错误,例如: main( ) int a; float a10; 变量名与数组名重名是错误的。,2. 常见错误 (1)数组下标从0开始计算,如a5表示数组a有 5个元素。分别为a0,a1,a2,a3,a4。 (2)定义数组时,数组长度值不能为变量。 例如: #define FD 5 main( ) int a3+2

26、,b7+FD; 是合法的。,但是下述说明方式是错误的。 main( ) int n=5; int an; (3)允许在同一个类型说明中,说明多个数组和多个变量。 例如: int a,b,c,d,k110,k220;,数组的类型实际上是指数组元素的取值类型。对于同一个数组,其所有元素的数据类型都是相同的。 (4)C语言规定,在对数组进行定义或对数组元素进行引用时必须要用方括号(对二维数组或多维数组的每一维数据都必须分别用方括号括起来),例如以下写法都将造成编译时出错: int a(10); int b5,4; printf(dn,b1+2,2);,任务2 二维数组 学习目标 了解二维数组的基本概

27、念、掌握数组类型变量的定义与引用、掌握数组元素的引用 。,案例一案例讲解 1.问题描述 以矩阵格式输出一个二维数组,数组的主对角线上的元素赋值为l,其他元素赋初值为0。,3.2.1 案例讲解,2. 编程分析 如果有一个一维数组,它的每一个元素是类型相同的一维数组时,就形成一个二维数组。我们可以把二维数组看作是一种特殊的一维数组:它的元素又是一个一维数组。例如:float a34;可以把a看作是一个一维数组,它有三个元素:a0、a1、a2,每个元素又是一个包含4个元素的一维数组。可以把a0、a1、a2看作是一维数组的名字。,3.编写源程序 /* EX3_8.C */ main( ) int a6

28、6,i,j; for(i=1;i6;i+) for(j=1;j6;j+) aij=(i/j)*(j/i); for(i=1;i6;i+) ,for(j=1;j6;j+) printf(%2d,aij); printf(n); 4. 运行结果如图3-10所示。 图3-10 案例1运行结果,5. 归纳分析 与一维数组元素引用相同,任何二维数组元素的引用都可以看成一个变量的使用,可以被赋值,可以参与组成表达式,也可输入输出。但要注意,其下标取值应限定在数组大小范围内,不能超界使用。,案例二 两个矩阵的和 1问题描述 有矩阵a和b如下图所示,求它们的和矩阵c 两个MN阶的矩阵a、b,其和矩阵也是一个M

29、N 阶的矩阵c。,2.编程分析 求和公式如下: cij= aij+bij 3. 编写源程序,/* EX3_9.C */ #include #define M 3 #define N 2 main( ) int aMN=9,-16,6,21,25,18; /* 数组a初始化 */ int bMN=16,89,26,-27,36,81; /* 数组b初始化 */ int i,j,cMN; for(i=0;iM;i+) for(j=0;jN;j+),cij=aij+bij; /* 生成c数组 */ for(i=0;iM;i+) /* 输出a、b、c三个数组 */ for(j=0;jN;j+) /*

30、输出a数组的第i行 */ printf(%5d,aij); printf( ); for(j=0;jN;j+) /* 输出b数组的第i行 */ printf(%5d,bij); printf( ); for(j=0;jN;j+) /* 输出c数组的第i行 */ printf(%5d,cij); printf(n); ,4. 运行结果如图3-11所示。 图3-11 案例2运行结果,5. 归纳分析 二维数组中的数组元素被排成行列形式的一组双下标变量,用一个统一的数组名和双下标变量来标识、第一个下标表示行,第二个下标表示列。下标也从0开始排列。 二维数组通常是和双重循环相配合,对数组元素依次进行处理

31、。,1二维数组的的说明、引入和存储 (1)二维数组的说明 语法 类型标识符 数组名常量表达式 常量表达式; 说明 常量表达式包含常量和符号常量,不能包含变量。,3.2.2 基础理论,如果有一个一维数组,它的每一个元素是类型相同的一维数组时,就形成一个二维数组。我们可以把二维数组看作是一种特殊的一维数组:它的元素又是一个一维数组。例如:float a34;可以把a看作是一个一维数组,它有三个元素:a0、a1、a2,每个元素又是一个包含4个元素的一维数组。可以把a0、a1、a2看作是一维数组的名字。 C语言中,二维数组中元素的排列顺序是:按行存放,即在内存中先顺序存放第一行的元素,,再存放第二行的

32、元素。数组a在内存中的存放顺序为: a00 a01 a02 a03 a10 a11 a12 a13 a20 a21 a22 a23 通常形象的把第一个下标称为行下标,第二个下标称为列下标。 例如 int varij,i代表行下标j代表列下标; 多维数组的定义方法与二维数组相仿: 例如 int var345,代表一个三维数组;,(2)二维数组的引用 引用形式 数组名下标下标 说明 例如:a11=3;a21=a11;printf(%dn,a11); 数组不能整体使用,只能逐个引用数组元素。 下标可以是整型常数、整型变量和整型表达式。,(3)二维数组的存储 对于mn的二维数组a,各元素的存储次序如下

33、: a00、a01 a0n-1、a10、a11a1n-1am-10、 am-11am-1n-1 系统为其分配的存储单元数为:mn每个元素占用的存储单元数其中,每个元素占用的存储单元数取决于数组的数据类型。例如, 22数组example的存储情况如图3-12所示:,图3-12 数组example的存储情况,2. 二维数组的初始化 二维数组的初始化有以下几种: (1)分组初始化 int a25=1,3,5,7,9,2,4,6,8 ,10; 这种赋值方法比较直观,把第一个花括号内的数据赋给第一行的元素,第二个花括号内的数据赋给第二行的元素 。,(2)不分行初始化 int a25=1,3,5,7,9,

34、2,4,6,8,10; 可以将所有数据写在一个花括号内,按数组排列的顺序对各元素赋初值。 (3)部分行初始化 int a25=1,3,5,2,4,6; 赋初值后数组各元素值为: a00=1, a01=3, a02=5, a03=0, a04=0, a10=2, a11=4, a12=6, a13=0, a14=0,(4)省略行数 int a23=1,3,5,7,9,11; 等价于:int a 3=1,3,5,7,9,11; 但不能写成:int a2 =1,3,5,7,9,11; 对数组中的全体元素都赋初值时,二维数组的定义中第一维的长度也可以省略,但二维的长度不能省略。,如: 在分行初始化时,

35、由于给出的初值已清楚的表明了行数和各行中元素的个数,因此第一维的大小可以不定义。如:int b 3=1,0,2,3,2,1;显然这是一个三行三列的数组,其各元素的值为: 100 020 321,【实验3.2.1】产生一个MN的随机数矩阵(数值范围在1100之间),找出其中的最大值元素。,3.2.3 技能训练,(1)编程分析 设矩阵数组为a,首先把第一个元素a00作为当前最大值max,然后把当前最大值max与每一个元素aij进行比较,若aijmax,把aij作为新的当前最大值,并记录下其下标i和j。当全部元素比较完后,max是整个矩阵全部元素的最大值。,(2)编程源程序 /* EX3_10.C

36、*/ #include #include stdlib.h #define M 3 #define N 4 void main( ) int i,j,row=0,col=0,max; int aMN; printf(建立随机数数组n );,for(i=0;imax) /* 将一个更大的值保存在max变量中 */ max=aij;,row=i; col=j; for(i=0;iM;i+) /* 输出随机数数组 */ for(j=0;jN;j+) printf(%5d,aij); printf(n); printf(随机数矩阵中最大值元素 a%d%d=%dn,row,col,max); /* 输出

37、结果 */ ,(3)在VC+集成环境中输入上述程序,文件存成EX3_10.C。如图3-13所示。 图3-13 运行结果,【实验3.2.2】一个学习小组有5个人,每个人有三门课的考试成绩,如表3-2。求全组分科的平均成绩和各科总平均成绩。 表3-2 成绩表,(1)编程分析 可定义一个二维数组a53存放五个人三门课的成绩。再定义一个一维数组v3存放所求得各分科平均成绩,设变量average 为全组各科总平均成绩。,(2)编程源程序 /* EX3_11.C */ #include void main( ) int i,j,s=0,average,v3,a53; printf(输入五个学生三门课的成绩

38、n); for(i=0;i3;i+) for(j=0;j5;j+), scanf(%d, ,(3)在VC+集成环境中输入上述程序,文件存成EX3_11.C。如图3-14所示。 图3-14 运行结果,【练习1】某年级共有3个班级,每班有N名学生,开设两门课程,要求分别对每个班级的学习成绩进行分等统计,并将统计结果保存在一个二维数组中。 /* EX3_12.C */ #include #define M 3 /* 定义班级数为3 */ #define N 5 /* 班级人数为5 */ main( ) ,3.2.4 拓展与练习,float a,b; int ave,i,j; static int r

39、esultM5; /* 定义保存统计结果的二维数组 */ for(j=0;jM;j+) for(i=1;i=N;i+) printf(Class %d achievement%d(a,b): ,j+1,i); scanf(%f,%f,switch(ave/10) /* 对第j的班级的学习成绩分等统计 */ case 10: case 9: resultj0+; break; /* j班优秀人数统计 */ case 8: resultj1+; break; /* j班良好人数统计 */ case 7: resultj2+; break; /* j班中等人数统计 */ case 6: result

40、j3+; break; /* j班及格人数统计 */ default: resultj4+; , /* j班不及格人数统计 */ for(j=0;jM;j+) for(i=0;i5;i+) printf(%5d,resultji); printf(n); ,上机运行程序并分析结果。 图3-15 运行结果,1常见错误 (1)常量表达式可以包含常量和符号常量,但不能包含变量。 例如:int a34; #define M 3 #define N 4 int aMN; int a31+3;,3.2.5 编程规范与常见错误,都是定义了一个3*4的二维数组a ,但不允许有如下定义: int n=4, m=

41、3; int amn int b3,4 int c(2)(3);,(2)二维数组可以看作一个特殊的一维数组,它的每个元素又是一个一维数组。例如上面定义二维数组a可以看作:数组a包含a0、a1、a2三个元素,而这三个元素均为一维数组。 a0包含a00、a01、a02、a03元素 a1包含a11、a11、a12、a13元素 a0包含a00、a02、a02、a03元素,任务3 字符与字符串 学习目标 掌握字符与字符串的区别,字符串的输入和输出,领会字符串操作函数。,案例一 字符统计 1.问题描述 输入20个字符,分别统计其中的数字个数和其他字符的个数。 2. 编程分析 字符数组中的每个元素均占一个字

42、节,且以ASCII代码的形式来存放字符数据。,3.3.1 案例讲解,3. 编写源程序 /* EX3_13.C */ #include main( ) char s20; int i,number=0,other=0; printf(输入20个字符); for(i=0;i20;i+)/* 建立有20个元素的字符数组s */ scanf(%c,for(i=0;i20;i+) /* 对s中的数字和其他字符进行分类统计 */ switch(si) case 0:/* 这10个连续的case用于判断数值型字符 */ case 1: case 2: case 3: case 4: case 5: case

43、 6: case 7: case 8: case 9:,number+; /* 对数字字符计数 */ break; default: other+; /* 对数字以外的其他字符计数 */ printf(数字个数 %d, 其他字符的个数%dn,number,other); ,4. 运行结果如图3-16所示。 图3-16 案例1运行结果,5. 归纳分析 字符串是一种常用的数据,处理人名,地址,文章等内容。单个字符(常量)放在一个字符变量中,字符串放在字符数组中。 案例二 字符的删除 1问题描述 由键盘任意输入一字符串和一个字符,要求从该串中删除所指定的字符。,2.编程分析 在语言中没有专门的字符串

44、变量,通常用一个字符数组来存放一个字符串。前面介绍字符串常量时,已说明字符串总是以0作为串的结束符。因此当把一个字符串存入一个数组时,也把结束符0存入数组,并以此作为该字符串的结束。,3.编写源程序 /* EX3_14.C */ #include main( ) char x,s20; int i,j; printf(输入一字符串); gets(s); printf(要删除指定的字符n);,scanf(%c, ,4. 运行结果如图3-17所示。 图3-17 案例2运行结果,5. 归纳分析 字符串结束符0是由C编译系统自动加上的。由于采用了0标志,所以在用字符串赋初值时一般无须指定数组的长度,

45、而由系统自行处理 。,字符数组是存放字符型数据的数组,其中每个数组元素存放的值均是单个字符。字符数组也有一维数组和多维数组之分。比较常用的是一维字符数组和二维字符数组。 1字符数组的说明、引用和初始化 字符数组的定义、初始化及引用同前面介绍的一维数组、二维数组类似,只是类型说明符为char,对字符数组初始化或赋值时,数据,3.3.2 基础理论,使用字符常量或相应的ASCII码值。 例如:char c10,str510;/* 字符数组的定义 */ 又如: char c3= r, e, d; /* 字符数组的初始化 */ printf(%c%c%cn,c0,c1,c2);/* 字符数组元素的引用

46、*/ 一个字符串可以放在一个一维数组中。如果有多个字符串,可以用一个二维数组来存放。,(1)字符数组的定义 用来存放字符数据的数组是字符数组。字符数组中的一个元素存放一个字符。 例如:char str12; (2)字符数组的初始化 在定义一个字符数组的同时,可以给它指定初值。有两种初始化的方法: 逐个为数组中各元素赋初值。如:,char str 8= C, o, m, p, u, t, e, r; 在对数组中的全体元素都赋初值时,字符数组的大小可以省略。 char str =C, o, m, p, u, t, e, r; 对一个字符数组指定一个字符串初值。例如 char str =“Compu

47、ter”; 注意单个字符用单引号括起来,而字符串用双引号括起来,在指定字符串初值的情况下,将字符串中的各字符逐个地按顺序赋给数组中的各,元素。注意:系统会自动在一个字符串的后面加一个“0”字符,并把它一起存入字符数组中。因此,上面的数组虽未定义大小,但系统自动将它定义为str 9,而不是str 8; C语言允许在初始化一个一维字符数组时,省略字符串外面的花括号。 如:char str =Computer; str的每个元素为char型,占1字节。,图3-18 一组字符数组初始化,(3)字符数组的引用 。与普通数组相同。 (4)字符串和字符串结束标志 语言允许用字符串的方式对数组作初始化赋值。

48、例如:char c =c, ,p,r,o,g,r,a,m; 可写为:char c =C program; 或去掉写为:char c =C program; 用字符串方式赋值比用字符逐个赋值要多占一个字节, 用于存放字符串结束标志0。上面的数组c在内存中的实际存放情况为:,(5)字符串的输入输出 用“%c”格式符输入输出字符串。 用“%s”格式符输入输出字符串。例如: char c6; scanf(%s,c); printf(%s,c); 说明: C语言中,数组名代表该数组的起始地址,,因此,scanf( )函数中数组名前不再加地址运算符 输出结果:China %s格式输出时,若数组中包含一个以

49、上0,遇第一个0时结束。,例如:char country20 = C,h,i,n,a,0,J,a,p,a,n,0; printf(%s, country); 输出结果:China 输入字符串时,遇回车键结束,但获得的字符中不包含回车键本身,而是在字符串末尾添加0。 用一个scanf( )函数输入多个字符串时,输入的各字符串之间要以“空格”键分隔。例如:,char str15,str25,str35; scanf(%s%s%s,str1,str2,str3); 输入数据:Howareyou? str1、str2、str3获得的数据情况如下: 图3-19 str1、str2、str3获得的数据情况

50、,(6)字符串处理函数 strcat( ) 函数原型:char *strcat(char *s1,char *s2); 功能说明: 用来连接两个字符串。其一般形式为: strcat(str1,str2); 将str2中的字符连接到str1的字符后面,并在最后加一个“0”。 连接后新的字符串存放在str1中,因此str1,必须定义的足够大。 如连接两个字符串。 strcpy( ) 语法: strcpy(字符数组1,字符数组2) 功能说明: C语言不允许用赋值表达式对字符数组赋值,如下面的语句是非法的:str1=“China。就像不允许把整个数组一起复制(int a5,b6; a=b;)到另一个数

51、组一样(因为数组名是个地址,通过数组名不知道数组的大小)。,如果想把字符串“China”放到字符数组中,除了可以逐个的输入字符外,还可以使用strcpy函数,将一个字符串复制到字符数组中:strcpy(str1,China); 说明: 在向str1数组复制时,字符串结束标志0一起被复制到str1中。 可以将一个字符数组中的字符串复制到另一个字符数组中。例如:strcpy(str1,str2);注意不能用“str1=str2;”语句来赋值。 strcmp( ),语法: strcmp(字符数组1,字符数组2) 功能说明: 用来比较两个字符串。其一般形式为: strcmp(str1,str2); 功

52、能说明: 从两个字符串中第一个字符开始逐个进行比较,直到出现不同的字符或遇到“0”为止,如果全部字符都相同,就是相等。若出现了不相同的字符,则以第一个不相同的字符为准。,如果字符串1等于字符串2,函数值为0; 如果字符串1大于字符串2,函数值为一正整数; 如果字符串1小于字符串2,函数值为一负整数。 strlen( ) 语法: strlen(字符数组) 功能说明: 用来测出一个字符串中的实际字符个数。其值为“0”之前的全部字符个数。,strlwr( ) 语法: strlwr(字符串) 功能说明: 大写字符转换成小写字符。 strupr( ) 语法: strupr(字符串) 功能说明: 小写字符

53、转换成大写字符。,【实验3.3.1】输入一行字符,统计其中单词的个数。 (1)编程分析 要统计单词的个数,首先需要把单词找出来,这需要对字符逐个检测。设长度是n的字符串已存储在字符数组text中,各字符元素分别为text0、text1、text2textn-1,当检测texti(i0)时,若满足下列条件,则,3.2.3 技能训练,必然出现新单词:texti-1=,int word,i; printf(输入一字符串); gets(text); if(text0= ) word=0; /* 字符串首字符为空格时,单词数置0 */ else if(text0!=0) word=1; /* 字符串首字

54、符不为空格,单词数置1 */ i=1; while(texti!=0) ,if(texti-1= ,(3)在VC+集成环境中输入上述程序,文件存成EX3_15.C。如图3-20所示。 图3-20 运行结果 【实验3.3.2】判断s2是否是s1的子串。 (1)编程分析,从s1字符串的第一个字符开始,依次与s2字符串的各字符比较,若均相同,则s2是s1的子串;否则再从s1的下一个字符(第2个字符)开始,依次与s2字符串的各字符比较,。设k1,k2分别表示s1串和s2串的长度,则最后一次应从s1的第k1-k2+1个字符开始(即s1k1-k2),依次与s2字符串的各字符比较,若存在不同字符,则s2肯定

55、不是s1的子串。,(2)编写源程序 /* EX3_16.C */ #include #include main( ) char s180,s280; int i=0, j, k, k1, k2, flag; printf(输入第一个字符串); gets(s1); /* 输入第一个字符串 */,printf(输入第二个字符串); gets(s2); /* 输入第二个字符串 */ k1=strlen(s1); /* 求第一个字符串的长度 */ k2=strlen(s2); /* 求第二个字符串的长度 */ flag=0; /* 标志变量flag初值为0,即假设s2不包含在s1中 */ while(

56、ik1-k2+1, if (s2j=0)/* 若退出循环时,s2j=0,则s2串包含在s1串中 */ flag=1; break; /* 确认s2串包含在s1串中,flag=1,退出循环 */ i+; /* 从s1的下一个字符开始继续检测 */ if(flag=1) printf (%s在 %s中n,s2,s1); else printf (%s 不在 %s中n,s2,s1); ,(3)在VC+集成环境中输入上述程序,文件存成EX3_16.C。如图3-21所示。 图3-21 运行结果,【练习1】输入五个国家的名称按字母顺序排列输出。 五个国家名应由一个二维字符数组来处理。然而语言规定可以把一个二维数组当成多个一维数组处理。 因此本题又可以按五个一维数组处理, 而每一个一维数组就是一个国家名字符串。用字符串比较函数比较各一维数组的大小,并排序,输出结果即可。,3.3.4 拓展与练习,/* EX3_17.C */ #include #include main( ) cha

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论