




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、教学目标:本章介绍C语言中数组的定义和使用,其中重点介绍一维数组的定义、引用、初始化本章重点 :一维数组的定义、初始化及应用;数组元素的引用方法:下标法、数组名法。本章难点: 利用指针实现对数组的操作;教学方法:理论教学与实践教学相结合。3.1 一维数组1问题的提出: 到目前为止,我们使用的都是属于基本的数据类型(即int、float、double、char以及int和float的一些变体)的数据。尽管这些数据类型都很有用,但是它们却只能用于处理数量有限的数据。当遇到大量数据的时候我们该怎么办呢?我们先看一个实际问题。 假设某计算机班有学生人数为30人,要编程实现录入该班学生的C语言程序设计课
2、程成绩,并将成绩按照从低分到高分的次序输出。2在编程的时候,我们先暂时不考虑排序的细节,先看如何存储这30个学生的成绩?很多初学者觉得这个问题很简单,就像声明实型变量一样声明30个实型变量(如:int a1,a2,a3,a30;),如果这样可以的话,那么若某年级的500名学生的C成绩都要处理,那将需要声明500个变量?很显然,这是不可能的。下面的知识帮助你处理多个同类型数据存储的知识数组数组属于是一组数据类型相同的变量的有限序列,序列中的每个变量称为数组元素。数组必须先定义后使用。 33.1 一维数组3.1.1. 一维数组的定义和初始化1一维数组的定义一维数组定义的一般形式为: 元素类型 数组
3、名常量表达式 数组的长度, 必须是常量或常量表达式数组元素的类型合法的用户定义标识符数组名是代表数组存储空间首地址的地址常量4 :下标运算符单目运算符优先级(1)左结合其中:下标可以是常量、变量或表达式数组元素就视作同类型的普通变量来使用。数组元素引用形式一:数组名下标如:int a6;定义了一个能够容纳6个整数的一维数组a。例如int a6;数组a中有6个元素,分别是:a0, a1, a2, a3, a4, a5。 如果有int i=2;则ai+2就是a4,是数组中第5个元素。数组元素的下标从0开始。5数组在内存中的分配: 系统自动为数组分配合适大小的连续的存储空间,数组元素按其下标递增的顺
4、序依次占用相应字节的内存单元。即数组是顺序存储的。数组所占字节数sizeof(类型)*数组长度。a00145a1a2a3a4a523a数组名表示数组内存首地址,是地址常量int a6;6注意示项:int n=10,an;/*error*/1)不能用变量定义数组长度。#define N 100 int aN,bN+10; /*correct*/72)C语言对数组不作越界检查,使用时要注意控制好元素引用范围。例 int data5; data5=10; /*编译没有错误,请问此处对数组元素的引用是否正确?*/3)数值型数组只能单个引用数组元素,不能用数组名一次引用整个数组。8 数组在定义时,可以为
5、数组元素赋初值。2一维数组初始化注意:数组定义时没有初始化时值的情况若数组定义时没有初始化,各元素均是随机值。例如 int a3; 此时a0,a1,a2都是随机值。若数组定义时前面加上static来修饰,整型数组各元素值是0,字符数组各元素值是0(ASCII码值0)。例如 static int a3;此时a0,a1,a2都是0。9 全部元素初始化在对全部数组元素初始化时,可以不指定数组长度。如:长度是10的数组a,a0到a9的值分别为:0,1,2,3,4,5,6,7,8,9。 请对数组a的初始化: int a10=0,1,2,3,4,5,6,7,8,9;或 int a =0,1,2,3,4,5
6、,6,7,8,9;/*初始化时不指定长度,则数组长度就是内的元素个数*/数组初始化方法有: 全部元素初始化 部分元素初始化。在定义数组时用“=”,将元素写在和 之间并用“,”分隔。10 部分元素初始化。 此时数组的长度不能省略。并且是赋值给前面的元素。 没有被赋值的数组元素,数值型数组时值为0,字符型数组时值为0。如: 1 2 0 0 0 int a5=1,2,i;for(i=0;i5;i+) printf(“%4d”,ai);运行结果11int a6,i;/*输入*/for(i=0;i6;i+) scanf(“%d”, );&ai3数组的输入、输出和赋值(1)输入:已知往整型数组a中输入6个
7、整数:注意:对于数值型数组必须每个元素逐个读值12int a6 , i;for(i=0;i6;i+) scanf(“%d”, &ai );/*输出*/for(i=0;i6;i+) printf(“%d”, ai);(2)输出:对于数值型数组必须每个元素逐个输出13(3)赋值 注意:数组名是地址常量,值不可改变,不允许对数组名进行赋值运算。例如:假设数组a中有元素1,2,3,则下面的赋值是错误的:int a3;a=1,2,3;/*error*/改成:int a3=1,2,3;或者 int a3; a0 = 1;a2 = 2; a3 = 3;注意在定义语句外,只能对数组元素进行单个引用14例如,想
8、要数组b和数组a的值相同,请问下面做法是否正确?指出并改正。 int a3=1,2,3,b3; b = a; int a3=1,2,3,b3,i; for(i = 0; i3;i+) bi = ai;/*error*/改成:15假设有一存放6个整数的数组a,编写程序,使得数组b和数组a的值相同。课堂编程练习:16【例3.1】编程,将整型数组a中的十个整型数逆序存放 并输出。数组编程的常用的两种方法:方法一:直接在原数组a中进行操作。方法二:辅设一个同长度的数组b,按要求先将原数组a中的元素按要求转换到b中,然后再将b中的元素拷贝回a中。通常方法二的思路简单,容易实现,方法一的算法难度大些。但方
9、法一的效率高,较方法二优秀。17方法一:直接在原数组中进行操作操作前 a: 1 2 3 4 5 6 7 8 9 10操作后 a: 10 9 8 7 6 5 4 3 2 1抓住值的变化特征很容易发现:a中第一个数和最后一个数交换,第二个数和倒数第二个数交换,直到中间两个数交换完毕,就实现了a的逆置。算法分析:18a: 1 2 3 4 5 6 7 8 9 10ij101ij92下标: 0 1 9算法思想:取得前后两个元素的值需要设置两个下标变量,假设是i,j。算法步骤:(1)i=0, j=9(2)如果 i=j结束19main() int a10,i,j,t; /*输入数据*/*数组逆置*/*输出数
10、据*/注意:数值型数组只能是单个元素输入,单个元素输出。for(i=0;i10;i+) scanf(%d,&ai);for(i=0,j=9;ij;i+,j-)t=ai;ai=aj;aj=t;for(i=0;i10;i+) printf(%4d,ai);算法实现:20方法二:辅设一个同长度的数组b算法分析:操作前 a: 1 2 3 4 5 6 7 8 9 10 辅设b:操作后a:10 9 8 7 6 5 4 3 2 1 10 9 8 7 6 5 4 3 2 121main() int a10,b10,i,j,t; for(i=0;i10;i+) scanf(%d,&ai); /*将a中的数据逆序
11、放到b中*/ for(i=0,j=9;i10;i+,j-) bj=ai; /*将中数据顺序写回a*/ for(i=0;i10;i+) bi=ai; for(i=0;i10;i+) printf(%4d,ai);算法实现:223.1.2指针与一维数组(难点) 数组元素的地址为: &数组名下标 例如: int a6; a00145a1a2a3a4a523a数组名表示数组内存首地址,是地址常量可以看成是指向元素a0的指针,但是常量数组元素a0的地址:数组元素a3的地址:&a0或a&a3。说明: 数组名不能取地址。原因:数组名是地址常量,对数组名取地址没有意义。23 main() int a6=1,2
12、,3,4,5,6,*p,*q; p=&a3; q=a; /*或者q=&a0*/ printf(“%3d%3dn”,*p,*q); 输出:1指向一维数组元素的指针变量 通过指针可以操作数组中的元素。 例3.2: 1 4242指针运算 除了赋值运算外,指向一维数组元素的指针,还可以进行下列运算: 指向数组元素的指针可以加(减)一个整型数。 例如:main() int a6=1,2,3,4,5,6,*p =&a2; printf(“%3d%3dn”,*(a+3),*(p-1); 输出:假设p是指向数组元素的指针, n是一个整型数,则:pn的含义:获得p所指元素的后(前)数第n个元素的地址。分析:a+
13、3等价于&a3,即a+3指向a3; p-1指向a1。4 225 指向数组元素的指针变量可以做自加自减运算p+或+p :等价于 p=p+1,自加后指向原来指向元素的下一个元素p- 或 -p:等价于p=p-1,自减后指向原来指向元素的前一个元素。注意:数组名是常量,不能进行自加自减运算。【结论】如果有定义int a100, *p=a; 则数组元素ai的地址可以表示成: &ai 或 a+i 或p+i26例3.3: main() int a6=1,2,3,4,5,6,*p,*q; p=&a3; q=p+; printf(“%3d%3dn”,*p,*q); 输出:5 427【例3.4】读程序写结果,注意
14、*和+运算符的优先级,及前置加和后置加的区别。 main() int a=1,3,5,*p; p=&a1; printf(*p+=%dn,*p+); printf(%dn,*p); p=&a1; printf(*p)+=%dn,(*p)+); printf(*p=%dn,*p); 注意:要想使得p所指向的变量的值加1应写成: (*p)+; 或者 +*p;/* 等价于*(p+) ,先使用*p然后p加1 */*先使用*p然后*p值加1 */【执行结果】*p+=3*p=5(*p)+=3*p=428【例3.5】用指向元素的指针变量来实现数组元素的逆置。取得数组中一个元素的位置有两种方法:方法一、用下标
15、 (逻辑顺序) 于是可以通过 ai, *(a+i)操作元素。方法二、用实际地址 (物理存储) 假设i是当前元素的实际地址,于是可以通过*i来操作元素。下面就是采用方法二来编程。 地址: a a+1 a+9 a: 1 2 3 4 5 6 7 8 9 10ij101ij9229for(i=a;ia+10;i+) scanf(%d,i);for(i=a,j=a+9;ij;i+,j-)t=*i; *i=*j; *j=t;for(i=a;ia为真,pa+4为假。313.1.3一维数组元素的指针法引用(数组元素的另两种引用方法)由前面的介绍可知,若有定义:int a10,*p=a;则&ai、(a+i)和(
16、p+i)是等价的,它们都表示数组元素ai的地址。由此下标为i的数组元素可以表示成: ai、 *(a+i)、*(p+i)、pi 等价。由此,一维数组元素可以用指针法引用。 数组名法指针变量法下标法321数组名法数组元素引用方法二用数组名引用数组元素的一般形式为:*(数组名+下标表达式)其中,表达式类型任意,一般为算术表达式,其值为数组元素的下标。如:*(a+3-1)表示数组元素a2。 【例3.4】用数组名法实现例3.1。将整型数组a中的十个整型数逆序存放并输出。33main() int a10,i,j,t; for(i=0;i10;i+) scanf(%d, ); for(i=0,j=9;ij;
17、i+,j-) for(i=0;i10;i+) printf(%4d, );*(数组名+下标表达式)a+it=*(a+i);*(a+i)=*(a+j);*(a+j)=t;*(a+i)main() int a10,i,j,t; /*输入数据*/ for(i=0;i10;i+) scanf(%d,&ai); /*数组逆置*/for(i=0,j=9;ij;i+,j-)t=ai;ai=aj;aj=t; /*输出数据*/ for(i=0;i10;i+) printf(%4d,ai);342指针变量法用指针变量引用数组元素的一般形式为:*(指针变量+表达式)其中,指针变量为指向一维数组元素的指针变量。表达式
18、类型任意,一般为算术表达式。【例题】int a10,*p=a+3;则下列用指针变量p对数组元素引用的都是正确的。适说明各语句的作用。*p=10 ; *(p+2*2)=20;*p+=40;/* 与a3=10等价 */* 与a7=20等价 */* 与*p=*p+40等价即a3+=40*/35指向数组元素的指针变量也可用下标法表示数组元素,即*(p+i)和pi是等价的。 main() int a10,*p=a;for(i=0;i10;i+) scanf(%d,&pi); /*数组逆置*/for(i=0,j=9;ij;i+,j-)t=pi;pi=pj;pj=t;/*输出数据*/for(i=0;i10;
19、i+) printf(%4d,ai);36课程项目案例二 学生成绩管理题目要求:要编写一个对某班学生C语言课程成绩进行管理的小程序,功能包括成绩信息录入、 显示、成绩查询、成绩插入、成绩删除、成绩排序。3.1.2 函数调用对一维数组编程37此处具体功能要求如下:(1)成绩信息录入:输入若干个学生的成绩。(2)显示:输出所有学生成绩。(3)查询:暂且为查询等于指定成绩的第一个学生的位置。到学会定义姓名数组之后该功能要改。(4)插入:指定位置插入一学生成绩。(5)删除:指定位置删除一学生成绩。(6)排序:将学生成绩按降序排序。38预备知识分析:(1)数据存储问题:很显然数据宜用数组来组织,当前字符
20、数组的知识还没学,所以暂且只用整型数组来存放若干个成绩。(2)设计思想:显然,这个程序的功能比较多,若都写在主函数中,显然代码过长,出错后不易调试。所以应采用模块化设计思想,将功能分解成独立的子模块,并用函数来实现。需要学习如何用函数实现对数组的操作 ?(3)要实现各个功能,需要学习数据的插入、删除、查找、排序等算法。393.1.2 函数调用对一维数组编程形参:使用指针变量,通常定义成数组(长度可以省略)实参:数组名参数传递规则:是地址传递,是将主调函数中数组空间的首地址给了形参变量40【例3.7】假设某班有30人,现有一数组已存放了若干个学生的成绩,函数调用编程:查询值等于x的第一个学生成绩
21、,找到后返回位序,没找到返回0。#include #define N 30 /*指定数组的容量*/*查找函数声明*/int search(int score,int n,int x);系统会自动将其视为int *score41main()int scoreN,i,n,x;printf(请输入录入成绩的数量(=30):);scanf(%d,&n);printf(请输入%d个学生的成绩:,n);for(i=0; in; i+) scanf(%d,&scorei);printf(请输入待查找的学生的成绩:);scanf(%,&x); /*查找函数调用与结果输出*/if(i=search(score,
22、n,x)=0)printf(成绩不存在!);elseprintf(该成绩是第%d个数据,i);42/*查找函数定义*/*在成绩数组score中查询值等于x的成绩第一次出现时的位置,找到后返回位序,没找到返回0。*/int search(int score,int n,int x)int i=0;while(in & scorei!=x) i+;if(in) return i+1;else return 0;必须保证在数组范围内进行查找43【例3.8】指定位置进行数据插入。 已知一组整数,要求在指定位置i处插入值x,成功返回1,失败返回0. 插入前 (a1, , ai-1, ai, , an)
23、插入后 (a1, , ai-1, x, ai, , an)0 1 i i+1 n-1a1 a2 ai-1 ai an an-1anai-1 x44算法思想:1)检查i值是否超出所允许的范围(1in+1),若超出,则返回0,插入失败;2) 将线性表的第i个元素和它后面的所有元素均逆序 向后移动一个位置;3)将新元素x写入到空出的第i个位置上;4)使数组的长度n增1。45/*在数组score中第i位置插入成绩x,成功返回1,失败返回0.*/int insert(int score,int *n,int i,int x) int j;if(i*n)return 0;/*将scoren-1到score
24、i-1间的数据后移*/for(j=*n-1;j=i-1;j-)scorej+1=scorej;scorei-1 = x;(*n)+; return 1;46#define N 30 /*指定数组的容量*/Void main() int scoreN, n, i,x; /*指定元素个数n*/ /*往数组score中输入元素*/ /*输入插入位置i*/ /*输入待插入的值x*/ /*调用插入函数*/ if(insert(score,&n,i,x) /调用结果是1 printf(插入成功n); else printf(插入失败n); /*显示插入后数组*/ 47【例3.9】指定位置进行数据删除。已知
25、一组整数,要求删除指定位置i处的元素,成功返回1,失败返回0. 删除前 (a1, , ai-1, ai, ai+1, an) 删除后 (a1, , ai-1, ai+1, , an)0 1 i-1 i n-2 n-1a1 a2 ai ai+1 an-1 an anai+1ai+248算法思想:1)检查i值是否超出所允许的范围(1in),若超出,则返回0,删除失败;2) 将线性表的第i+1个元素和它后面的所有元素均正序前移一个位置;3)使数组的长度n减1。49/*删除成绩数组score中第i个成绩,成功返回1,失败返回0.*/int delete(int score,int *n,int i)
26、int j;if(i*n)return 0;/*将scorei到scoren-1间的数据前移*/for(j=i;j=*n-1;j+)scorej-1=scorej;(*n)-; return 1;主函数略50【例3.10】数据由小到大升序排序。数据排序的方法有很多种下面介绍三种较简单的排序方法:直接插入排序简单选择排序冒泡排序511、用直接插入排序实现一组整数升序排序。排序过程:参看图示排序思想:先将第一个数看成有序序列,然后一次将后面的数插入到前面有序序列中。共经过n-1趟排序,排序结束。52 i=6 (13 27 38 49 65 76 97) 49例49 38 65 97 76 13 2
27、7 49i=1 (38 49) 65 97 76 13 27 49i=2 (38 49 65) 97 76 13 27 49i=3 (38 49 65 97) 76 13 27 49i=4 (38 49 65 76 97) 13 27 49i=5 (13 38 49 65 76 97) 27 49 ( )i=7 (13 27 38 49 49 65 76 97)排序结果: (13 27 38 49 49 65 76 97)53i=6 (13 38 49 65 76 97) 27 49jjjjjj977665493827)i27t一趟插入排序的实现过程:54void InsertSort(int
28、 a,int n)int i,j,t;for(i=1;i=0 & ajt)aj+1=aj; j-;/存入待插元素aj+1=t;55#define N 30void main()int scoreN,i,n;printf(请输入录入成绩的数量(=30):);scanf(%d,&n);printf(请输入%d个学生的成绩:,n);for(i=0; in; i+) scanf(%d,&scorei);/*调用插入排序*/InsertSort(score,n);/*输出排序结果*/ for(i=0; in; i+) printf(%4d,scorei);562、用简单选择排序法实现一组整数升序排序。选择排序过程:参看图示(1)从N个元素中找出值最小的元素,将其与第一个元素值交换。(2)从剩下的N-1元素中找出值最小的元素,将其与第二个元素值交换。(3)如此下去,重复上述过程,直到剩下一个最大数。 共经过n-1趟排序,排序结束。57例初始: 49 38 65 49 76 13 27 kjjjjjjkk1349一趟: 13 38 65 49 76 49 27 kkjjjjj2738二趟: 13 27 65 49 76 49 38 三趟: 13 27 38 49 76 49 65 四趟: 1
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 教练和女儿私下协议书
- 咖啡厅加盟合同协议书
- 财产账户协议书
- 药店变更协议书
- 邮储就业协议书
- 屠宰检疫员合同协议书
- 合同外增加工程协议书
- 邮寄快递协议书
- 液化气供气合同协议书
- 美国导弹协议书
- 施工钢结构制作安装环境因素识别表
- 污水井巡查记录表
- 2关于更换现场项目经理的函
- 部编版小学道德与法治四年级下册期末复习简答及分析题专练(含答案)
- 电子商务那些事学习通超星课后章节答案期末考试题库2023年
- 环境及理化因素损伤-冻伤
- Unit7SeasonPartALetslearn(教学设计)闽教版英语四年级下册
- 世界文化遗产武当山古建筑群的资料
- 医院医疗设备采购项目HIS系统及硬件采购投标文件
- 【橡胶工艺】-橡胶产品生产工艺规程
- 推销实战技巧与客户优秀服务技巧
评论
0/150
提交评论