计算机与信息技术学院大一上c语言13-1数组ianme_第1页
计算机与信息技术学院大一上c语言13-1数组ianme_第2页
计算机与信息技术学院大一上c语言13-1数组ianme_第3页
计算机与信息技术学院大一上c语言13-1数组ianme_第4页
计算机与信息技术学院大一上c语言13-1数组ianme_第5页
已阅读5页,还剩38页未读 继续免费阅读

下载本文档

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

文档简介

1课程内容第一章程序设计和C语言第二章数据对象与计算第三章变量、函数和控制结构第四章基本程序设计技术第五章C程序结构(函数)第六章数组第七章指针第八章文件和输入输出第九章结构和其它数据机制第十章程序开发技术第十一章标准库2第十三部分数组3语言需要提供一套数据机制,描述与数据有关的问题:必须足够丰富,以满足需要;不能过庞杂,臃肿难用;也不能太低级,使描述过于烦琐。高级语言的数据机制:把数据分为类型,每个类型是一个数据集。提供一组基本数据类型;确定其书写方式;为各类型提供一组基本操作。提供一组由简单数据类型或对象构造复合数据类型或对象的机制。组合的数据对象称为复合数据对象。由所有“同类的”复合对象形成的类型称为复合数据类型,组成部分称为成分/成员/元素。4基本类型构造类型指针类型空类型void定义类型typedef数值类型字符类型char

8位枚举类型enum整型浮点型单精度型float

32位双精度型double

64位短整型short

16位长整型long

32位整型int

16位数组结构体struct共用体unionC数据类型由基本类型数据按一定规则组成的,也称为“导出类型”数组5问题:输入学生的学号,成绩,

计算平均成绩,

计算每个学生的成绩与平均成绩的差,

差>=10成绩等级A0<=差<10成绩等级B

其它成绩等级C

设:学号doublen1,n2,n3,n4,…,n30;

成绩doubles1,s2,s3,s4,…,s30;能否:一个变量名对应多个连续的存储单元:数组数组是程序中最常用的结构数据类型,用来描述由固定数目的同一类型的元素组成的数据结构6数组的概念、定义和使用数组程序实例数组作为函数参数字符数组和字符串两维和多维数组编程实例主要内容71数组的概念、定义和使用数组(array):是多个同类型数据对象的组合。一个数组汇集了多个数据项,数组元素。可从数组出发处理各元素,以统一方式处理一批/所有元素,是数组和一组独立变量的主要区别。为此需要:数组描述,数组变量定义,初值化数组使用,包括通过数组变量使用其元素数组实现,数组的存储方式8数组变量定义定义数组变量(定义数组)时需说明:数组元素类型数组(变量)名数组(变量)的元素个数(也称数组大小或长度)定义方式:

数据类型数组名[常量表达式];

例,定义两个数组:

inta[10];

doublea1[100];数组定义可以与其他变量定义写在一起,如:

inta2[16],n,a3[25],m;方括号内整型表达式说明元素个数,表达式应能静态确定值,可用字面量或枚举常量9可定义外部数组和局部数组,包括局部静态数组(用static),作用域与存在期与简单变量相同。数组的外部说明不必描述数组大小。例:

externinta[];externdoublea1[];下面函数里数组定义不合法:voidf(intm,intn){

intb[n];/*非法,编译时无法确定大小*/....} 新C99标准支持这种定义,满足C99的编译器很少10基本操作是元素访问。元素顺序编号,首元素序号0,其余顺序编号。n元数组元素编号是0到n-1。定义:

intb[100];元素编号为0、1、2、…、99。称为下标或指标。元素访问通过[]运算符,优先级最高,运算对象是数组名和括号里表示下标的表达式。表达式、语句里的b[3]称为下标表达式或带下标的变量。例:有上面定义后,可写:

b[0]=1;b[1]=1; b[2]=b[0]+b[1]; b[3]=b[1]+b[2];数组的使用11数组的真正意义在于能以统一方式描述对一组数据的处理。下标表达式可用一般的整型表达式。如:

b[i]=b[i-1]+b[i-2];访问哪个元素由i值确定。同一语句可访问不同元素,可用在循环里访问一批元素。for(i=0;i<100;++i){

b[i]+=a1[i]*a2[i];}/*假设数组都有定义*/循环中涉及到300个基本数据对象。12#include<stdio.h>intmain(){longfib[30];intn;fib[0]=1;fib[1]=1;for(n=2;n<30;++n)fib[n]=fib[n-1]+fib[n-2];

for(n=0;n<30;++n)

{printf("%d",fib[n]);putchar(n%6==5?'\n':'');}/*6个数输出一行*/return0;}例:写程序创建包含前30个Fibonacci数的数组,然后打印数组中所有的数。13对数组的多个或全部元素操作,常用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不检查数组元素访问的合法性,运行中出现越界不会报错。超范围访问是严重错误,后果无法预料。14数组的负数下标C语言只规定数组的下标必须是整型数据,因此负数下标也合法,但是语义上是否正确,取决于用负数下标访问时是否越界。……a[-1]a[-2]…a[0]a[2]a[3]a[1]…内存空间例给定数组、函数及其调用inta[10];intfunc(intarr[],intn);func(&a[2],8);则在func内部,对arr[-2]和arr[-1]的访问分别对应于a[0]和a[1],是合法的,并没有产生实际的越界,在arr[-3]就不一定能保证语义正确性了。1516数组的实现数组占据一片连续存储区,元素顺序排列,0号元素在最前面,各元素占相同空间。如有:

inta[8];a的存储恰好能存放8个整型数据,情况如图:a至少相当于8个int变量,a[0]~a[7]可以看作“变量名”。保证元素排在一起,能以统一方式使用。数组名表示内存首地址,是地址常量编译时分配连续内存内存字节数=数组元素个数*

sizeof(元素数据类型)17在一些系统里越界访问可能导致动态错,系统强行终止出错的程序。越界可能破坏本程序的数据/程序本身/其他软件,甚至是整个系统。编程者要保证数组下标值的合法性,保证不越界。数组初始化定义数组时可直接初始化。外部、局部静态或自动数组都可在定义时进行初始化。方法一:定义时直接初始化intb[4]={1,1,2,3};doubleax[6]={1.3,2.24,5.11,8.37,6.5};

初值表达式必须是常量表达式。外部和静态数组在程序开始执行前建立并初始化,局部自动数组在程序执行进入相应函数或复合语句体时建立和初始化18这种写法只能用于数组初始化,不能用在语句里。若定义时未初始化,外部和局部静态数组的元素自动初始化为0;自动数组处在不明确的状态。方法二:只为部分元素提供初值,其余元素将自动置0。初始化表元素个数不得超过数组元素个数。例:

intb1[4]={1,2};b1[2]、b1[3]将给初值0。方法三:若给了所有元素的初值,可以不写数组大小而只写方括号,元素个数由初值个数确定。例:intfib[]={1,1,2,3,5,8,13,21,34,55};这种写法能减少维护负担,有利于程序修改。在语句中对数据元素赋值的方法?19说明:数组必须先定义,后使用只能逐个引用数组元素,不能一次引用整个数组数组元素表示形式:数组名[下标]其中:下标可以是常量或整型表达式//顺序输入输出数组元素#include<stdio.h>voidmain()

{ inti,a[10]; for(i=0;i<10;i++) a[i]=i; for(i=0;i<=9;i++) printf(“%4d”,a[i]);}//将数组元素逆序输出#include<stdio.h>voidmain()

{ inti,a[10]; for(i=0;i<10;i++) a[i]=i; for(i=9;i<=0;i--) printf(“%4d”,a[i]);}例一维数组的输入与输出。20数组的概念、定义和使用数组程序实例数组作为函数参数字符数组和字符串两维和多维数组编程实例主要内容212数组处理程序实例例:从字符到下标(整数)写程序统计由标准输入得到的文件中数字字符的个数。

可定义10个计数变量,用if或switch区分情况,遇数字字符(isdigit)时对应计数器加1。不需要数组。将字符看作整数可得到另一解法。常见字符集里数字顺序排列,ASCII字符集里0到9的编码是48到57。利用这个事实,用10个元素的计数器数组可以更方便地完成对数字出现的统计。22intcs[10];用cs[0]记录'0'出现次数,余类推。若c是数字,对应计数器加1可以写成:++cs[c-'0'];/*c-'0'正是对应计数器的下标*/#include<stdio.h>#include<ctype.h>intcs[10]={0,0,0,0,0,0,0,0,0,0};intmain(){

intc,i;while((c=getchar())!=EOF)if(isdigit(c))++cs[c-'0'];for(i=0;i<10;++i)printf("Digit%d:%d\n",i,cs[i]);return0;}23例:筛法求素数筛法是求素数的著名方法:用空间换时间,1亿以内的素数只需要十几秒的时间(如不考虑输出)具体算法:取2开始的整数序列:令n等于2,它是素数;划掉序列中所有n的倍数;令n等于下一未划元素(它是素数),回到步骤2。用数组表示整数序列,以元素下标表示对应整数。数组an,an[0]代表0,an[i]代表i。每个数只需表示划掉或未划掉,用0/1表示。开始时元素置1(即假设所有元素都是素数),而后不断将元素置0,直到确定了给定范围里的所有素数。

24假设NUM是给定范围:/*建数组an,元素初始化1,将an[0]和an[1]置0(它们不是素数)*/for(inti=2;i值不大于某个数;++i)if(an[i]==1)//i是素数

for(intj=i*2;j<NUM;j+=i)an[j]=0;/*i的倍数都不是素数*/外层循环何时结束?可用NUM作为界限。检验一个数是不是素数,只要看比它的平方根小的素数是不是能整除它

,因此只要i超过NUM的平方根,就可以划掉到既定范围内的所有合数。123456789101112131415161718192021222324251不算遍历一遍,划掉2的倍数:得235791113151719212325遍历一遍,划掉3的倍数:得2357111317192325遍历一遍,划掉5的倍数:得2357111317192325#include<stdio.h>enum{NUM=200};intan[NUM+1];intmain(void){inti,j;an[0]=an[1]=0;/*建立初始向量*/for(i=2;i<=NUM;++i)an[i]=1;for(i=2;i*i<=NUM;++i)

if(an[i]==1)for(j=i*2;j<=NUM;j+=i)an[j]=0;for(i=2,j=0;i<=NUM;++i)if(an[i]!=0)printf("%d",i);putchar('\n');return0;}26例:成绩分类写程序输入一批学生成绩(≤200)。先输出不及格成绩,再输出及格成绩,最后输出不及格和及格的人数。

无法在输入过程中完成(除非输入两遍)。用数组记录学生成绩,输入记入数组,而后输出,可避免重复输入

数据装入数组后有许多可能处理方法。最简单的是两次扫描数组,第一次输出不及格成绩,第二次输出及格的成绩。统计工作可在某次扫描中完成(也可在输入中完成),两部分人数之和就是总人数,统计一部分就够了。27enum{NUM=200};constdoublePASS=60.0;doublescores[NUM];intmain(){inti,n=0,fail;

while(n<NUM&&scanf("%lf",&scores[n])==1)++n;

/*输入时需要判断不越界*/

for(fail=0,i=0;i<n;++i)if(scores[i]<PASS)

{printf("%f\n",scores[i]);++fail;}

for(i=0;i<n;++i)if(scores[i]>=PASS)printf("%f\n",scores[i]);printf("Fail:%d\nPass:%d\n",fail,n-fail);return0;}28例:多项式求值设数组p中存放下列多项式的系数,其中p[i]存放写程序求p表示的多项式在指定点的值。方法1:求出各项值累加。假设指定点值存于x:for(sum=0.0,n=0;n<TERMS;++n){for(t=p[n],i=1;i<=n;++i)t*=x;sum+=t;}循环体内可以改写为(先算x的幂):

for(t=1.0,i=1;i<=n;++i)t*=x;sum+=t*p[n];可发现有大量重复计算。29通过保存前次的t值:for(sum=0.0,t=1.0,n=0;n<TERMS;++n){sum+=t*p[n];t*=x;}方法2:多项式可以变形为Horner范式:按照这个公式,求值循环可写为:for(sum=0.0,n=TERMS-1;n>=0;--n)sum=sum*x+p[n];从计算量上比较它们:需要多少次加法,多少次乘法。30定义数组的问题如果数组表示的是全局数据集合,需要在多个函数里使用,那么可考虑定义为外部数组。大的数组应定义为外部,以免占大量运行栈空间。一般系统不允许在函数内定义特别大的数组。若数组保存着递归定义函数的局部数据,就必须定义为自动数组。因为递归调用时需要数组的多份拷贝。其他情况可以根据需要自由选择。31数组的概念、定义和使用数组程序实例数组作为函数参数字符数组和字符串两维和多维数组编程实例主要内容323数组作为函数参数

数组可以作为函数的参数,但是在向函数传递数组时通常有两种方法:即:

“地址”的传递

“值”的传递

33方法一:

用数组名作为实际参数,给函数传递数组的地址,通过这个地址就可以访问到数组的元素了——双向传递。#include<stdio.h>#defineN20voidf(intb[],intn,intm){inti;for(i=m;i>=n;i--)b[i+1]=b[i];}voidmain(){inti,a[N]={1,2,3,4,5,6,7,8,9,10};f(a,2,9);for(i=0;i<5;i++)printf(“%4d”,a[i]);}a12345678910

b1098764531

2

3

3

434方法二:

用数组元素作为实际参数,是一种传值的方式,即:调用函数时要复制数据——单向传递。

#include<stdio.h>intfmax(intx,inty){ return(x>y?x:y);}

voidmain(){

inta[10],j,max;

for(j=0;j<=9;j++)

scanf(“%d”,&a[j]);

max=a[0];

for(j=1;j<=9;j++)

max=fmax(max,a[j]);

printf(“\n最大值为:%8d\n”,max);}35对函数参数的小结:“值”传递形参和实参都是普通变量实参是数组元素,形参是普通变量“地址”传递:形参、实参都是数组名,完成双向传递。完成单向传递36假设有多个数组都需要求平均值?解决方法:定义以数组为参数的函数。以数组为参数,不同调用可以完成对不同数组的计算。定义以double类型的数组为参数求元素平均值的函数,就可解决所有double数组的平均值问题设常量LEN是被处理数组的长度。doubleavg0(double

a[])

{doublex=0.0;inti;for(i=0;i<LEN;++i)x+=a[i];returnx/LEN;}/*注意:数组形参不需要写数组大小*/37若数组a1长LEN,可用:

x=avg0(a1);avg0有一定通用性,若数组a2长度也是LEN:

y=avg0(a2);用符号常量指定数组大小可解决许多问题。缺点:若数组长度不是LEN,就不能用avg0处理。可见:avg0不够通用,只能正确处理长为LEN的数组。参数是使函数能处理一类问题的基本机制。为提高数组处理函数的通用性,定义时应引进长度参数,使函数能处理任何给定长度的数组。38改造后的函数:doubleavg(intlen,doublea[]){doublex=0.0;inti;for(i=0;i<len;++i)x+=a[i];returnx/len;}对调用提出的新要求:必须正确提供数组长度。应用实例:intmain(){doubleb1[]={1.2,2.43,1.74},b2[]={6.5,9.2,8.6,4.5,0.3};printf("%f,%f\n",avg(3,b1),avg(5,b2));return0;}39长度参数提高了函数的通用性。但使用时必须关注越界问题。avg(5,b1)引起数组越界(b1有3个元素)。长度实参可小于数组大小,avg(3,b2)求b2前3个

温馨提示

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

评论

0/150

提交评论