




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第6C内容提要数组类型;向函数传递一维数组和二维数组;常用算法:排序、查找、求最大最小值等;用字符数组存取字符串;使用字符串处理函数处理字符串C提供了一组基本类型:int、double等。除了基本数据类型,还有一些组合的数据类型,称为构造数据类型。(书上18页)构造机制包括数组、指针、结构、联合。可用它们组合数据对象,作为整体使用。
组合的数据对象称为复合数据对象。复合对象形成的类型称为复合数据类型,组成部分称为成分/成员/元素。可创建能存放复合类型数据的变量。这种变量可作为整体使用,通过名字可以访问整个复合对象。也可以访问复合数据对象的成分,如:使用成分的值或给成分赋值。
本章介绍数组就是常见的组合机制。数组的用处保存大量同类型的相关数据的问题-例如,输入全班30个学生的成绩,并排出名次。-例如,矩阵运算,表格数据等。为什么使用数组例子:要读入某班全体50位同学某科学习成绩,然后进行简单处理(求平均成绩、最高分、最低分……)若用简单变量,需50个不同变量名,要用很多个scanf命令
intscore1,score2,…score50;
scanf("%d,%d,%d",&score1,&score2,&score3); scanf("%d,%d,%d",&score4,&score5,&score6);而用数组,可共用一个scanf命令并利用循环结构读取
intscore[50],i; for(i=0;i<50;i++){scanf("%d",&score[i]);
}保存大量同类型的相关数据6.1数组的概念、定义和使用数组(array)是多个同类型数据对象的组合。一个数组汇集了多个数据项,数组元素。可从数组出发处理各元素,以统一方式处理一批/所有元素,是数组和一组独立变量的主要区别。为此需要:数组描述,数组变量定义数组使用,包括通过数组变量使用其元素数组实现,数组的存储方式数组变量定义定义数组变量(定义数组)时需说明:数组元素类型数组(变量)的元素个数
元素个数也称数组大小或长度。定义数组变量时,方括号内整型表达式说明元素个数,表达式应用静态确定值,可用字面量或枚举常量。例,定义两个数组:
inta[10]; doublea1[100];数组定义可以与其他变量定义写在一起,如:
inta2[16],n,a3[25],m;定义
存储类型
数据类型数组名[整数1][整数2]……[整数n];a[9]a[8]a[7]a[1]a[0]…数组首地址inta[10];定义一个有10个int型元素的数组系统会在内存分配连续的10个int空间给此数组直接对a的访问,就是访问此数组的首地址使用a[0]、a[1]、a[2]、……、a[9]这样的形式访问每个元素。可以像使用普通变量一样使用他们。数组(Array)的实现数组大小最好用宏来定义,以适应未来可能的变化#defineSIZE10
inta[SIZE];数组大小定义好后,将永远不变#include<stdio.h>#defineSIZE10main(){
inta[SIZE];
……}也可定义外部数组和局部静态数组(用static)。作用域与存在期与简单变量相同。数组的外部说明不必描述数组大小。例:
externinta[];
externdoublea1[];下面函数里数组定义不合法:voidf(intm,intn){intb[n];/*非法,编译时无法确定大小*/....} 新C99标准支持这种定义,满足C99的编译器很少根据数组的数据类型,为每一元素安排相同长度的存储单元根据数组的存储类型,将其安排在内存的动态、静态存储区或寄存器区用sizeof(a)来获得数组a所占字节数short数组的存储结构
一维数组占用字节数=数组长度×sizeof(基类型)数组使用基本操作是元素访问。元素顺序编号,首元素序号0,其余顺序编号。n元数组元素编号是0到n-1。定义:
intb[100];元素编号为0、1、2、…、。称为下标或指标。元素访问通过[]运算符,优先级最高,运算对象是数组名和括号里表示下标的表达式。表达式、语句里的b[3]称为下标表达式。例:有上面定义后,可写:
b[0]=1;b[1]=1; b[2]=b[0]+b[1]; b[3]=b[1]+b[2];99数组意义在于能以统一方式描述对一组数据的处理。下标表达式可用一般的整型表达式。如:
b[i]=b[i-1]+b[i-2];访问哪个元素由i值确定。同一语句可访问不同元素,可用在循环里访问一批元素。for(i=0;i<100;++i){b[i]+=a1[i]*a2[i];}/*假设数组都有定义*/循环中涉及到300个基本数据对象。对数组的多个或全部元素操作,常用for语句。令变量遍历数组下标:
for(n=0;n<数组长度;++n)...问题:fib是30个元素的数组,假设程序里写:
for(n=2;n<=30;++n) fib[n]=fib[n-1]+fib[n-2];循环中试图访问fib[30],实际无此元素。用超范围的下标访问称为越界访问,是数组使用中最常见的错误。使用大于最大下标的下标,将访问数组以外的空间。那里的数据是未知的。下标值超范围是运行中的问题。C不检查数组元素访问的合法性,运行中出现越界不会报错。超范围访问是严重错误,后果无法预料。在一些系统里越界访问可能导致动态错,系统强行终止出错的程序。DOS不检查非法访问,越界可能破坏本程序的数据/程序本身/其他软件,甚至DOS系统。编程者要保证数组下标值的合法性,保证不越界。数组定义后的初值仍然是随机数,一般需要我们来初始化定义数组时可直接初始化。外部、局部静态或自动数组都可在定义时进行初始化。定义时初始化的例子:intb[4]={1,1,2,3};doubleax[6]={1.3,2.24,5.11,8.37,6.5};inta[5]={0};inta[]={11,22,33,44,55};初值表达式必须是常量表达式。对自动数组也一样。数组初始化这种写法只能用于数组初始化,不能用在语句里。若定义时未初始化,外部和局部静态数组的元素自动初始化为0;自动数组不自动初始化。可只为部分元素提供初值,其余元素将自动置0。初始化表元素个数不得超过数组元素个数。例:
intb1[4]={1,2};b1[2]、b1[3]将给初值0。若给了所有元素的初值,可以不写数组大小而只写方括号,元素个数由初值个数确定。例:intfib[]={1,1,2,3,5,8,13,21,34,55};这种写法能减少维护负担,有利于程序修改。快速地随机访问一旦定义,不能改变大小数组的特点只能逐个对数组元素进行操作(字符数组例外)输入方法:inta[10],i;输入第i个数组元素:scanf("%d",&a[i]);输入整个数组元素:for(i=0;i<10;i++)scanf("%d",&a[i]);输出方法:输出第i个数组元素:printf("%d",a[i]);输出整个数组元素:for(i=0;i<10;i++)printf("%d",a[i]);一维数组的输入和输出举例:请登记某班级数学成绩,再输出#include<stdio.h>#defineARR_SIZE40main(){
floatscore[ARR_SIZE];
intn,i;
longnum[ARR_SIZE];
printf("Pleaseentertotalnumber:");
scanf("%d",&n);/*从键盘输入学生人数n*/
printf(“Pleaseenterthenumberandscore:\n”);
for(i=0;i<n;i++)/*分别以长整型和实型格式输入学生的学号和成绩*/{scanf("%ld%f",&num[i],&score[i]);}
printf("Yourenterthenumberandscore:\n");
for(i=0;i<n;i++){
printf("%d%f\n",num[i],score[i]);}
system("pause");}一维数组和多维数组一维数组用一个下标确定各元素在数组中的顺序可用排列成一行的元素组来表示如inta[5];二维数组用两个下标确定各元素在数组中的顺序可用排列成i行,j列的元素组来表示如intb[2][3];n维数组用n个下标来确定各元素在数组中的顺序如intc[3][2][4];n≥3时,维数组无法在平面上表示其各元素的位置a[0]a[1]a[2]a[3]a[4]b[0][0]b[0][1]b[0][2]b[1][0]b[1][1]b[1][2]二维数组的定义数据类型数组名[常量表达式][常量表达式];inta[2][3];a[0]a[1]a----a[0][0]a[0][1]a[0][2]----a[1][0]a[1][1]a[1][2]【例一】以下程序的运行结果是什么?main(){inta[][3]={{1,2,3},{4,5},{6},{0}};printf("%d,%d,%d\n",a[1][1],a[2][1],a[3][1]);}123450600000结果:5,0,0【例二】若inta[][3]={1,2,3,4,5,6,7},则a数组的第一维大小是多少?
123456700二维数组的初始化示例数组的引用数组名[下标1][下标2]……[下标n]下标都是从0开始,养成从0开始查数的职业病使用a[0]、a[1]、a[2]、……、a[9]这样的形式访问每个元素数组下标(index)既可以是常量,也可以是整型表达式,允许快速地随机访问.可以像使用普通变量一样使用他们数组的引用数组名[下标1][下标2]……[下标n]下标越界是大忌!编译程序不检查是否越界下标越界,将访问数组以外的空间那里的数据是未知的,不受我们掌控,可能带来严重后果二维数组的存储结构shortinta[2][3];a[0]a[1]a[1][0]a[1][1]a[1][2]a[0][0]a[0][1]a[0][2]存放顺序:先顺序存放第0行的元素再存放第1行的元素a[0][0]a[0][1]a[0][2]a[1][0]a[1][1]a[1][2]所以需要知道数组的每一行有多少列,这样从起始地址开始,才能正确的读出数组的元素按行存放二维数组占用字节数=第一维长度×第二维长度×
sizeof(基类型)二维数组所占的存储空间的计算:二维数组的输入和输出数组的输入和输出只能逐个对数组元素进行操作(字符数组例外)inta[2][3],i,j;输入方法:输入第i行第j列元素:scanf(“%d”,&a[i][j]);输入整个数组元素:for(i=0;i<2;i++)for(j=0;j<3;j++)scanf(“%d”,&a[i][j]);输出方法:输出第i行第j列元素:printf(“%d”,a[i][j]);输出整个数组元素:for(i=0;i<2;i++)for(j=0;j<3;j++)printf(“%d”,a[i][j]);如何使两个数组的值相等main(){inta[4]={1,2,3,4},b[4];
b=a;
}解决方法法1:逐个元素赋值
b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];法2:通过循环赋值
inti;for(i=0;i<4;i++){
b[i]=a[i];}原因:数组名表示数组的首地址,其值不可改变!如何使两个数组的值相等如何使两个二维数组的值相等?通过双重循环赋值
inta[4][2]={1,2,3,4,5,6,7,8};intb[4][2];inti,j;for(i=0;i<4;i++){for(j=0;j<2;j++){
b[i][j]=a[i][j];}}例6.1兔子繁殖问题打印每个月和年底时的总的兔子对数Fibonacci数列123581321345589144233,…
233144895534211385321总对数:89553421138532110小兔对数:1448955342113853211大兔对数:121110987654321月份:图中蓝色实线表示大兔仍是大兔,红色实线表示小兔长成大兔;绿色虚线表示大兔生小兔。不难看出:年末有大兔子144对,小兔子89对,总共144+89=233对深入观察:上月有几对大兔子,这月就有几对小兔子,即:
每月小兔子对数=上月大兔子对数每月大兔子对数=上月大兔子对数+上月小兔子对数综合①②有:每月大兔子对数=前两月大兔子对数之和每月大兔子对数公式例6.1#include<stdio.h>#defineYEAR_MONTH12main(){
intf[YEAR_MONTH+1]={0,1,2};
intmonth;
for(month=3;month<=YEAR_MONTH;month++) { f[month]=f[month-1]+f[month-2]; }
for(month=1;month<=YEAR_MONTH;month++) {
printf("%d\t",f[month]); }
printf("\nsum=%d\n",f[YEAR_MONTH]);}每月兔子总对数公式max(i=0)max(i=2)max(i=3)计算最大值算法200801200802200803200804……200838数组编号:学号:成绩:0123……383988759078……maxScore:maxNum:因为88>75,所以88保留因为90>88,所以用90替换88由于90分所在的数组编号是2,记下该编号,去找到学号数组中的数组编号,并替换8820080120080390例6.2—打印最高分从键盘输入学生人数n;从键盘输入所有学生的学号和成绩分别存入数组num和score假设其中的一个学生成绩为最高
maxScore=score[0]; 对所有学生成绩进行比较,即
for(i=1;i<n;i++){
若score[i]>maxScore 则修改maxScore值为score[i]
}打印最高分maxScore......main(){ ......
for(i=0;i<n;i++) { scanf("%ld%f",&num[i],&score[i]); }
maxScore
=score[0];
for(i=1;i<n;i++) {
if(score[i]>maxScore) {
maxScore
=score[i];
} } printf("maxScore=%.0f\n",maxScore);}例6.2—打印最高分......main(){ ......
for(i=0;i<n;i++) { scanf("%ld%f",&num[i],&score[i]); } maxScore=score[0];
maxNum=num[0];
for(i=1;i<n;i++) {
if(score[i]>maxScore) { maxScore=score[i];
maxNum=num[i];
} } printf("maxScore=%.0f,maxNum=
%ld\n",maxScore,
maxNum);}例6.2—打印最高分及其学生序号用函数实现?#include<stdio.h>#defineARR_SIZE40floatFindMax(floatarr,intn);main(){
floatscore[ARR_SIZE],maxScore;
intn,i;
printf("Pleaseentertotalnumber:"); scanf("%d",&n); printf("Pleaseenterthescore:\n");
for(i=0;i<n;i++) { scanf("%f",&score[i]); } maxScore=FindMax(score,n); printf("maxScore=%.0f\n",maxScore);}floatFindMax(floatarr[],intn){
floatmax;
inti;
max=arr[0];
for(i=1;i<n;i++) {
if(arr[i]>max) { max=arr[i]; } } }现场编程
用函数实现打印最高分关于函数的参数传递:对于一般变量作为函数的形式参数,调用函数的时候,用“单项值传递”的方法来将实参的值复制给形参,形参有值后,参与计算,得出需要的值,而后随着调用的结束,形参变量消失。intAverage(intx,inty){intresult;result=(x+y)/2;returnresult;}main(){inta=12;intb=24;intave;ave=Average(a,b);
printf(……);}数据传递执行顺序实参形参形参值在此处完成函数运算,并消失但是如果用数组作为函数的形式参数:由于每次调用函数,作为形式参数的数组,每次都要重新开辟一块连续的存储空间,每次复制一堆的实参值,用完又马上将内存还给系统。需要的系统开销太大。因此,C程序设计语言规定,数组作形式参数时,不重新开辟存储空间,而是用实际参数已有的空间。floatFindMax(floatarr[],intn){
floatmax;
inti;
max=arr[0];
for(i=1;i<n;i++) {
if(arr[i]>max) { max=arr[i]; } } }此处虽然写成数组形式,但不真正开辟形式参数的内存空间,只产生一个用来存放地址的变量。这里这样写是为了说明此处需要放一个数组,作为实际参数
数组名作函数参数传递整个数组到另一个函数内,实际上是将数组的首地址作为参数传过去用数组名作为函数参数只拷贝一个地址自然比拷贝全部数据效率高由于首地址相同,故实参数组与形参数组占用同一段内存在该函数内,不仅可以读这个数组的元素,还可以修改它们简单变量和数组作函数参数的区别#include<stdio.h>#defineARR_SIZE40floatFindMax(floatarr,intn);main(){
floatscore[ARR_SIZE],maxScore;
intn,i;
printf("Pleaseentertotalnumber:"); scanf("%d",&n); printf("Pleaseenterthescore:\n");
for(i=0;i<n;i++) { scanf("%f",&score[i]); } maxScore=FindMax(score,); printf("maxScore=%.0f\n",maxScore);}floatFindMax(floatarr[],int
){
floatmax;
inti;
max=arr[0];
for(i=1;i<
;i++) {
if(arr[i]>max) { max=arr[i]; } } }现场编程
用函数实现打印最高分向函数传递一维数组时,最好同时再用一个参数传递数组的长度n作业P2286.4~6.76.9现场演示排序算法交换法排序选择法排序交换法排序交换法排序交换法排序交换法排序for(i=0;i<n-1;i++){
for(j=i+1;j<n;j++){
if(score[j]>score[i])
"交换成绩score[j]和score[i]",
"交换学号num[j]和num[i]";
}}如何实现两数交换?如下方法是否可行:
score[j]=score[i];score[i]=score[j];试想一下,一个瓶子装酱油,一个瓶子装醋,现在将这两个瓶子交换装的东西,如何交换?答案:必须再拿一个空瓶子,用来腾空其中一个瓶子。选择法排序k=1k=2k=0k=1选择法排序k=3k=4k=3k=4选择法排序选择法排序for(i=0;i<n-1;i++){
k=i;
for(j=i+1;j<n;j++){
if(score[j]>score[k])记录此轮比较中最高分的元素下标k=j;
}
若k中记录的最大数不在位置i,则
"交换成绩score[k]和score[i]",
"交换学号num[k]和num[i]";}现场演示查找算法顺序查找折半查找顺序查找intSearch(longa[],intn,longx){
inti;
for(i=0;i<n;i++){
if(a[i]==x){
return(i);}}
return(-1);}哈,找到了!折半查找数组下标0123456第一次循环:9901199013990159901799019
①查找值x=99017lowmidhighx>a[mid],low=mid+1第二次循环:9901199013990159901799019
low=midhighx=a[mid],找到哈,找到了!折半查找数组下标0123456第一次循环:9901199013990159901799019
②查找值x=99016lowmidhighx>a[mid],low=mid+1第二次循环:9901199013990159901799019
low=midhighx<a[mid],high=mid-1第三次循环:9901199013990159901799019
highlow不满足low<=high,循环结束,未找到
唉,没找到!intBinSearch(longa[],intn,longx){
intlow,high,mid; low=0; high=n-1;
while(low<=high) { mid=(high+low)/2;
if(x>a[mid]) { low=mid+1; }
else
if(x<a[mid]) { high=mid-1; }
else
{
return(mid); } }
return(-1);}向函数传递二维数组实际传送的是指向数组第一个元素的地址在声明二维数组形参时,不能省略数组第二维的长度,为什么?
a[0][0]a[0][1]a[0][2]a[1][0]a[1][1]a[1][2]a[0][0]a[0][1]a[0][2]a[1][0]a[1][1]a[1][2]例6.8计算每门课程的总分和平均分voidTotal(int
score[][COURSE],
intsum[],
floataver[],intn){
inti,j;
for(j=0;j<COURSE;j++) { sum[j]=0;
for(i=0;i<n;i++) { sum[j]=sum[j]+score[i][j]; } aver[j]=(float)sum[j]/n; }}可以省略数组第一维的长度不能省略数组第二维的长度字符串(String)与字符数组字符串一串以'\0'结尾的字符在C语言中被看作字符串用双引号括起的一串字符是字符串常量,C语言自动为其添加'\0'终结符C语言并没有为字符串提供任何专门的表示法,完全使用字符数组和字符指针来处理字符数组每个元素都是字符类型的数组charstring[80];字符数组的初始化用字符型数据对数组进行初始化charstr[6]={'C','h','i','n','a','\0'};charstr[]='C','h','i','n','a'};用字符串常量直接对数组初始化charstr[6]={"China"};charstr[6]="China";charstr[5]={"China"};
仅为字符型一维数组,不是字符串仅为字符型一维数组,不是字符串二维字符数组初始化charweekday[7][10]=
{”Sunday”,”Monday”,”Tuesday”,”Wednesday”,”Thursday”,”Friday”,”Saturday”};charweekday[][10]=
{”Sunday”,”Monday”,”Tuesday”,”Wednesday”,”Thursday”,”Friday”,”Saturday”};但不可写成:charweekday[][]=
{”Sunday”,”Mo
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 临床护理专业小组建设与管理
- 防火涂料包工协议书
- 节目演出安全协议书
- 饭店散伙转让协议书
- 订单合同融资协议书
- 银行股东分红协议书
- 公交车联合经营协议书
- 通校学生安全协议书
- 隔离酒店租用协议书
- 转让经营项目协议书
- 2025购销茶叶合同范本
- 山东济南历年中考作文题与审题指导(2005-2021)
- 武汉各区2023-2024学年九下化学四调压轴题分类汇编-第8题选择题
- 脑血管造影术的术前及术后护理
- 外墙涂料施工劳务合同范本(8篇)
- 成人重症患者颅内压增高防控护理专家共识2024
- 老产品芯片1-gc2145d模组设计指南
- 广东省中山市20222022学年下学期期末考试八年级英语试卷
- 油脂制取与加工工艺学
- 创新创业指导把握创业机会课件
- 第三章工程师的责任 工程伦理学课件
评论
0/150
提交评论