语言最基础到指针、文件-课件c06数组_第1页
语言最基础到指针、文件-课件c06数组_第2页
语言最基础到指针、文件-课件c06数组_第3页
语言最基础到指针、文件-课件c06数组_第4页
语言最基础到指针、文件-课件c06数组_第5页
已阅读5页,还剩37页未读 继续免费阅读

下载本文档

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

文档简介

C语言与程序设计江汉大学数学与计算机科学学院韩海数组21、数学上的数列 有穷数列:a1,a2,a3,…,an

无穷数列:a1,a2,a3,…,an,…

特点: 所有数据是同一种类型 数据间有顺序 从1开始计算下标2、数组 用一片连续的存储区域依次存放各个数据 特点: 所有数据是同一种类型 数据间有顺序 从0开始编排下标概念:数据元素数组与数列3把如下一组整数放到内存中

15,28,19,37,32,12,20,26准备内存预先确定数据的个数,考虑最大需要,记作N;每个数据需要多少字节,记作K;总共需要N×K字节的存储区。存放形式首元素放在连续存储区最小地址处相邻元素在内存中连续存放放完所有元素后,允许内存有空余元素数量需要另外准备一个变量记载当前这一片存储区中已经存放了多少个元素在内存中存放数组中的数据值 地址10001004100810121016102010241028103215281937321220264说明:1.定义数组就是命令计算机准备若干字节的连续内存,“类型”决定每个元素需要多少字节,可以是int、float、char等,“类型”对应的字节数可以用sizeof(类型)得到,它与“元素个数”的乘积就是总共需要的内存字节数。2.“元素个数”必须是常量,或由常量构成的计算式,不能是变量。3.“初值表”是用逗号分隔的若干个数据项,用于命令计算机在准备内存空间的同时把这些数据依次放到对应位置。4.“元素个数”不得小于“初值表”中数据项的数量(即不能出现放不下的情况)。如果两者相等,则定义数组时“元素个数”可以缺省;如果“初值表”所给数据项不足,则不足部分补0。5.不使用格式中的“={初值表}”时,则只命令计算机准备内存,内存中的内容由计算机“自由”安排。6.当“类型”相同时,可以在一行中定义多个数组以及普通变量。定义数组---准备内存格式A: 类型数组名[元素个数];格式B: 类型数组名[元素个数]={初值表};5解释以下各变量定义的含义:

doubles[4]={1.23,4.56,7.8,9}; doublet[]={1,2,3,4,5,6}; intn,data[3*2-1],i; intm[200]={1,2,3,4,5,6,7,8,9,10};指出以下变量定义违背了哪些语法规则(设其中未定义的符号为常量):

intnum;a1;a2; intdo[3]; intp(num); intx.1[NUM]; floaty[2]={1.1,2.2,3.3}; chars[]='a','b','c';定义数组示例6对于变量定义

intn,dt[3*2-1]={1,2,3,4},i;定义数组是定义了“一组变量”而不是“一个变量”,其中的每一个称为一个“数组元素”,有时也以“数组元素”称其中存放的数据。不能访问整个数组,只能单独地访问各个数组元素。指称某个数组元素的方法是: 数组名[下标]“下标”从0到“元素个数-1”依次编排,对于上面定义的数组dt,各元素分别是:

dt[0],dt[1],dt[2],dt[3],dt[4]访问数组元素时,“下标”可以是常量、变量,也可以是表达式数组是一组变量ndt[0]dt[1]dt[2]dt[3]dt[4]i值 地址10001004100810121016102010241028××12340××7对于变量定义

intdt[5]={1,2,3,4};用赋值语句把数据送到某个数组元素中,一次只能访问一个元素。

dt[3]=13; dt[1]=6; dt[0]=23; dt[4]=27; dt[2]=18; dt[1]=16;

前5条语句不能写作:

dt={23,6,18,13,27};

注意不要把赋值语句与变量定义混淆。从键盘读入数据送到某个数组元素中 例如:

scanf("%d%d",&dt[2],&dt[0]);Q:(1)如何从键盘读入5个整数存放到dt[0]到dt[4]中?

(2)如果数组共有500个元素,如何从键盘读入500个整数存放到dt[0]到dt[499]中?访问数组元素8对于前面的问题:

(1)读入5个整数可以写作:

scanf("%d%d%d%d%d",&dt[0],&dt[1],&dt[2],&dt[3],&dt[0]); (2)读入500个整数可以用循环实现

for(i=0;i<500;i++)

scanf("%d",&dt[i]);从数组元素中取出数据使用用于计算,如:

x=dt[2]+dt[4]*2-dt[0];把元素值显示到屏幕上,如:

printf("%d,%d,%d\n",dt[0],dt[1],dt[2]); for(i=0;i<5;i++) printf("%d\n"),dt[(i*3+2)%5]);访问数组元素(续)9Q:vx是由N个元素构成的数组,颠倒其中的存放次序,即把vx[0]中存放的数据与vx[N-1]中存放的数据交换,把vx[1]中存放的数据与vx[N-2]中存放的数据交换,...颠倒数组元素存放次序for(i=0;i<N/2;i++){temp=x[i];x[i]=x[N-i-1];x[N-i-1]=temp;}分析:1.总共需要进行N/2组的元素交换,可以用一个循环计数变量i从0到N/2计数,进行相应的控制;2.交换的对象是第i下标的元素和第N-i-1下标的元素,即vx[i]与vx[N-i-1];3.以一个变量为中间过渡,交换两个数组元素的值。10补充:随机函数(VC版)VC中有一个产生随机数的工具,它可以模拟日常生活中的很多随机现象,产生指定范围内均匀分布的随机数。随机数工具的用法包括三个要点:(1)在main的前面用include包含文件“windows.h”,写作

#include<windows.h>(2)在main中先用“srand(X);”语句把随机数系统初始化,其中的“X”要求是一个随机值,可以用系统运行时的时间作为这个值,写作:

srand(GetCurrentTime());(3)每次使用“rand()%n”产生一个0到n-1之间的随机非负整数。例如:#include<stdio.h>#include<windows.h>main(){inti;srand(GetCurrentTime());for(i=0;i<5;i++)printf("%5d",rand()%100);}第一次执行结果如下:1712631573第二次执行结果如下:54148323第三次执行结果如下:102658352111补充:随机函数(TC版)TC中同样有产生随机数的工具,用法包括三个要点:(1)在main的前面用include包含文件“stdlib.h”,写作

#include<stdlib.h>(2)在main中先用“randomize();”语句把随机数系统初始化;(3)每次使用“random(n)”产生一个0到n-1之间的随机整数。例如:#include<stdio.h>#include<stdlib.h>main(){inti;randomize();for(i=0;i<5;i++)printf("%5d",random(100));}上述程序可以在TC或者Win-TC中编译运行。12数组应用示例---模拟掷骰子Q:用随机数工具模拟掷骰子现象:掷100次骰子,显示每次是哪个面朝上,并统计六个面朝上各出现了多少次。分析:1.骰子共有六个面,各个面上的数字分别是1到6,用“rand()%6”可以产生0到5之间的随机数,加1后就在1到6之间。2.可以使用100次随机数工具,每次得到的数当作是掷骰子的结果。3.为了统计各个数出现的次数(即各个面朝上的次数),可以先准备有6个元素的数组t,各元素初值为0。以t[0]记录1号面朝上的次数,t[1]记录2号面朝上的次数,…t[5]记录6号面朝上的次数。4.每模拟一次掷骰子的情况,就把数组t相应下标的元素值加1。13模拟掷骰子的程序(VC版)#include<stdio.h>#include<windows.h>main(){intt[6]={0},i,k;srand(GetCurrentTime());printf("Dice100times:\n");

for(i=0;i<100;i++) /*以变量i控制循环100次*/{k=rand()%6; /*产生一个0到5之间的随机数*/printf("%4d",k+1);/*显示随机数(加1之后),代表1到6号面*/t[k]++; /*把数组t记录相应面的元素值加1*/}printf("\n\nStatisticalresult:\n");for(i=0;i<6;i++)printf("F%d:%dtimes.\n",i+1,t[i]);}下面是该程序某次运行的结果Statisticalresult:F1:18times.F2:16times.F3:19times.F4:11times.F5:20times.F6:16times.Q:用产生随机数的方式模拟一次考试的成绩是否合适?为什么?

14数组应用示例——查找查找通常分为以下几种情况:1.是否存在满足条件的数组元素——“存在性问题”最简单的查找方法就是“顺序查找”,即逐个检查每一个数据,直到发现目标值为止,或者找完了所有数据也没有发现目标。无论是哪一种情况,都可以做出“是否存在”的判断。2.找出所有满足条件的数组元素——变形的“完全性问题”逐个检查每一个数组元素,满足条件则做相应的处理,否则继续查看下一元素3.查找最大(最小)的数组元素15查找数组中满足条件的元素仿照“判断素数”的方法---标记法,在x[0]到x[n-1]中查找元素e

判断素数的流程 查找的流程i<n?-1k根据k的值下结论i+1ix[i]==e?YN0iikYNi<n?0k根据k的值下结论i+1in能被i整除?YN2i1kYN16查找指定值的程序段在x[0]到x[n-1]中查找元素e,可以用下面的程序段实现k=-1;for(i=0;i<n;i++)if(x[i]==e){ k=i; break;}if(k==-1)printf("Notfound.\n");elseprintf("Found.\n");下面的程序段能完成同样的任务:k=0;while(k<n&&x[k]!=e)k++;if(k<n)printf("Found.\n");else printf("Notfound.\n");Q:

1.如上右侧的程序段是如何实现查找操作的?与左边的处理方法有什么异同?2.相同条件下,哪一个程序段能更快地确定查找的结果?3.如果数组中目标值e出现了多次,两个程序段各能找到e的第几次出现?4.修改程序段,查找e的最后一次出现。17查找最大值Q:设x[0]到x[n-1]中的元素互不相同,查找其中的最大值是几号下标。方法要点:先假设x[0]最大,用变量k记录下标0;从1到n-1逐个查看数组各元素,如果比x[k]更大,说明k记错了,立即改成更大那个元素的下标。注意:最大值是一定存在的。i<n?0k结论:x[k]最大i+1ix[i]>x[k]?YN1iikYNfor(k=0,i=1;i<n;i++)if(x[i]>x[k])k=i;printf("x[%d]最大\n",k);18选择排序由x[0]到x[n-1]构成的数组,调整各个元素的存放位置,使得所有元素按由小到大的次序排列。

x[0]x[1]x[2]x[3]x[4]x[5]x[6]x[7]x[8]x[9]

221590472305764474667231191517221590472305517474667231191764221590472305517474191231667764221231472305517474191590667764221191231305472474517590667764191221231305472474517590667764…

…第1趟第2趟第3趟第4趟第9趟19选择排序(续)选择排序方法的要点:1.n个元素共做n-1趟扫描;2.每趟扫描找出当前剩余元素中最大值的位置,与最后一个元素交换。for(i=1;i<n;i++){

找x[0]到x[n-i]的最大元素, 对应的下标k

交换最大元素x[k]与尚未 排序的最后一个元素x[n-i]}k=0;for(j=1;j<=n-i;j++)if(x[k]<x[j]) k=j;t=x[k];x[k]=x[n-i];x[n-i]=t;Q:你还知道哪些排序的方法,描述它们的流程。20二维数组的概念数学上的矩阵:

a1,1a1,2

…a1,na2,1a2,2

…a2,n

…am,1am,2

…am,n1.m行n列的矩阵共有mn个元素;2.下标分为行下标和列下标;3.下标从1开始计数。C语言二维数组各元素间的逻辑关系:

a[0][0]a[0][1]…a[0][n-1]a[1][0]a[1][1]…a[1][n-1]a[m-1][0]a[m-1][1]…a[m-1][n-1]1.m行n列的矩阵共有mn个元素;2.下标分为行下标和列下标分别用两个方括号表示;3.下标从0开始计数。二维数组在内存中的存放----“行优先”原则a[0][0]a[0][1]…

…a[0][n-1]a[1][0]a[1][1]…

…a[1][n-1]…

…a[m-1][0]a[m-1][1]…

…a[m-1][n-1]0#行1#行m-1#行211.该定义命令计算机准备若干字节的连续内存,总共需要的内存字节数由sizeof(类型)、行数、列数三者的乘积确定。2.“行数”、“列数”必须是常量,或由常量构成的计算式。3.“初值表”允许两种形式:(1){{第0行初值表},{第1行初值表},…,{第m-1行初值表}}(2){初值项,初值项,…,初值项}

建议使用前一种写法。4.不允许出现放不下的情况;如果“初值表”所给数据项不足,则不足部分补0;初值表中数据齐全时,“行数”可以缺省;不允许缺省“列数”。5.不使用格式中的“={初值表}”时,则只命令计算机准备内存,内存中的内容由计算机“自由”安排。6.可以在一行中混合定义普通变量、一维数组和二维数组,但“类型”必须相同。定义二维数组---准备内存格式: 类型数组名[行数][列数]={初值表};22说明下面的变量定义的效果及内存分配情况:

intx1,x[4]={1,2,3};inty1[3][5]={1,2,3};intz1[3][5]={{1},{2},{3}};定义二维数组示例定义了一个普通的整型变量x1,一个具有4个元素的一维数组x,两个各自具有3行5列共15个元素的二维数组y1和z1。共计需要70字节的内存。x1的初值由计算机安排;x各元素的初值依次是1、2、3、0;y1的0#行前三个元素初值为1、2、3,其余初值为0;z1各行首元素初值依次为1、2、3,每行其余4个元素初值为0。x1x[0]x[1]x[2]x[3]y1[0][0]y1[0][1]…

…y1[2][3]y1[2][4]z1[0][0]z1[0][1]…

…z1[2][3]z1[2][4]××12301200100023矩阵乘法矩阵乘法:二维数组A中存放了一个M行N列的矩阵,二维数组B中存放的是N行L列的矩阵,A×B将得到一个M行L列的矩阵C,且C的第i行j列元素Ci,j的值通过下式计算得到:其中:0<=i<M,0<=j<Lfor(i=0;i<M;i++)for(j=0;j<L;j++){

计算Ci,j}s=0;for(k=0;k<N;k++)s+=A[i][k]*B[k][j];C[i][j]=s;24杨辉三角杨辉三角形是指如下的形状: 1 11 1 2 11 3 3 11 4 6 4 1

…用二维数组存放杨辉三角形:1

11

121

1331

14641

存储特点:用二维数组的左下三角形部分(含主对角线)即可存放;最左列和主对角线元素为1;其余元素为其左上方和正上方的元素值的和。25存放n行的杨辉三角定义一个N行N列的二维数组y[N][N],N可根据实际需要选取一个适当的常量;产生各元素值的主要程序段如下:for(i=0;i<n;i++)for(j=0;j<=i;j++){if(j==0||i==j) /*如果是最左列或主对角线*/

y[i][j]=1; else /*否则用左上角加正上方*/

y[i][j]=y[i-1][j-1]+y[i-1][j];}3.注意存放时是按直角三角形的形式,但显示时需要按等腰三角形的形式处理。26趣味问题:模拟在二维图形中行走奇幻方问题: 行走的规则包括:(1)如果右上角的格是空的,往右上角走(2)如果右上角的格不空(已填上数字),往下走(3)站在最上一行时,其“右上角”是网格的最底一行向右一列的格(4)站在最右一列时,其“右上角”是网格的最左一列向上一行的格(5)站在网格的右上角时,其“右上角”是网格的左下角方格(6)站在最下一行时,“往下走”则走到网格最上一行同列的格中迷宫问题:(1)M行N列共MN格构成(2)每格有4个相邻格,有些相通有些不通(3)有指定的入口和指定的出口(4)试探法找从入口到出口的路径27在二维图形中行走的技术解决奇幻方问题、迷宫问题等可能会用到以下技巧:需要用一对变量记录当前所在的坐标,其初值就是指定的入口“游戏规则”通常规定每次向前走一步,可另取一对变量记录(试探)可以走到哪一格每走到新的一格,通常需要对该格做相应的处理,比如做一定的标记表示已经到过此格如果需要,可以用适当的机制记载到目前为止所走过的路径如果向前不能再走时,可考虑“退一步”可以用下面的循环模式控制:

while(当前格不是出口) { 试探下一格的位置; 对下一步走到的格做相应的处理; 记录已走过的路径; 把所走到的那一格置为当前格;

}28多维数组如果有必要,可以定义三维数组甚至更多维的数组变量。从一维数组和二维数组的定义及使用方法可以类推出三维数组的有关用法。比如:

intx[3][3][4];计算机将准备72字节,共36个变量。x[0][0][0]x[0][2][0]x[2][2][0]x[2][2][3]x[0][2][3]x[0][0][3]x[2][0][3]x[0][0][0]x[0][0][1]x[0][0][2]x[0][0][3]x[0][1][0]x[0][1][1]x[0][1][2]x[0][1][3]x[0][2][0]…

…x[1][0][0]…

…x[2][2][3]C语言与程序设计江汉大学数学与计算机科学学院韩海字符数组与字符串30存放字符的数组: chars1[8]={'a','b','c','d','e'}; chars2[]={65,66,67,68,0};对应的内存分配图见右。字符型数据的存储字符型数据的显示

printf("%c%d",s1[2],s1[2]);显示结果为:

c99字符数组'a''b''c''d''e'000s2[0]s2[1]s2[2]s2[3]s2[4]s1[0]s1[1]s1[2]s1[3]s1[4]s1[5]s1[6]s1[7]65666768001100011s1[2]31字符串——由若干个字符构成的符号串字符串的各个符号在内存中依次、连续存放内存中的字符串,如何规定一个字符串到何处结束?

(1)指定“串长”的方法(通用,不限于字符串) (2)添加“结束符”的方法(C使用的方法)

结束符:0,'\0';不是'0'

存储形式:内存中的字符串,如何规定一个字符串从何处开始?

——没有规定必须从字符数组0#下标开始,可以在使用字符串时,指定一个起始位置Q:右图从'b'开始的字符串是什么? 右图中有几个什么样的字符串?字符串的概念1'a''b''c''d''e'0006566676800000000032C语言中以字符串作为字符数组初值时,以下写法等价

"abcde" 等价于 {'a','b','c','d','e','\0'}注意区分以下写法的异同:

chars3[]="abcde"; chars4[]={'a','b','c','d','e'}; chars5[6]={'a','b','c','d','e'};双引号中可以使用转义符,如:

chars6[]="A1%%B2\nC:\\"

其中有两个转义符,注意%%不是转义,仅在printf中有效串长——字符串中包含的有效字符个数(不计结束符)字符串的概念2Q:如果依次定义s3到s5,假设从内存地址100处开始安排,画出内存图。从内存100处开始存放的字符串的串长是多少?从内存103处开始存放的字符串的串长是多少?从内存107处开始存放的字符串的串长是多少?100102104106108110112114116118s3[0]'a''b''c''d''e''\0's4[0]'a''b''c''d''e's5[0]'a''b''c''d''e''\0'33Q:已知字符数组str中存放了一个字符串,编写程序段把各个字符依次显示到屏幕上。

for(i=0;str[i]!='\0';i++) putchar(str[i]);系统为显示字符串专门设计了两个工具,都当作语句使用:1.printf("%s",串起始地址); “串起始地址”通常有以下两种写法:

(1)&字符数组名[下标]

意为取某字符数组指定下标元素的地址

(2)字符数组名——数组名就是数组首元素的地址 对第(1)种写法,当“下标”为0时,可以简作“字符数组名”, 即第(2)种写法是第(1)种写法在下标为0时的特例2.puts(串起始地址);

等价于 printf("%s\n",串起始地址);字符串输出34Q:写出下列程序的运行结果

#include<stdio.h> main() {chars[]="1234567"; inti; for(i=0;i<7;i++) puts(&s[i]); }字符串输出示例结果如下:1234567234567345674567567677试用putchar(…)的方式进行输出,改写该程序inti,j;for(i=0;i<7;i++){for(j=i;s[j]!='\0';j++) putchar(s[j]); putchar('\n');}}35系统为从键盘读入字符串也专门设计了两个工具:1.scanf("%s",串起始地址);2.gets(串起始地址);

大致相当于scanf("%s",串起始地址);功能:从键盘读入多个符号,从“串起始地址”开始逐个依次存放,直至输入串结束,最后添加一个串结束符'\0'。输入方式:都是等待型输入,光标闪烁等待操作人员按键,直至最后按下回车键。差异:gets把回车前的所有按键作为字符串,而scanf在遇到空格后即认为输入串终止。例:charss[10]={'0','1','2','3','4', '5','6','7','8','9'};

scanf("%s",ss);按键是 AaBbCc字符串输入'0''1''2''3''4''5''6''7''8''9'ss[0]ss[1]ss[2]ss[3]ss[4]ss[5]ss[6]ss[7]ss[8]ss[9]'A''a''\0'gets(ss);'A''a''''''B''b''C''c''\0'36C语言系统为字符串处理也专门设计了几个工具:strlen(串首地址)

求从“串首地址”开始的字符串串长。计算结果为整数。strcmp(串1,串2)

按扩展的字典排序法比较两个字符串的大小。如果前小后大,计算结果为负整数;如果两个串完全对应相同,计算结果为0;如果前大后小,计算结果为正的整数。strcpy(串1,串2)

把“串2”复制到“串1”所指定的位置,并以“串1”(首元素地址)作为计算结果。strcat(串1,串2)

把“串2”添加到“串1”的后面,并以“串1”(首元素地址)作为计算结果。注意:1.程序中只要使用了任何一个串处理函数,都要在程序前面加上

#include<string.h>2.通常前两个函数当作求值工具使用,后两个函数当作处理工具使用。字符串处理函数37#include<stdio.h>#include<string.h>main(){chars[50];inti,k1,k2;gets(s);k1=strlen(s);

k2=0;for(i=0;s[i]!='\0';i++) k2++;printf("k1=%d\n",k1);printf("k2=%d\n",k2);}strlen的实现如果键盘上的按键是:

123XYZ则显示结果如何?k1=9k2=938#include<stdio.h>#include<string.h>main(){chars1[80],s2[80];intk,i;printf("S1=");gets(s1);printf("S2=");gets(s2);

k=strcmp(s1,s2);if(k<0) printf("S1<S2\n");else if(k==0) printf("S1=S2\n"); else printf("S1>S2\n");}strcmp的实现下面的程序段能否替代程序中蓝色的一行?i=0;while(s1[i]!='\0' &&s2[i]!='\0' &&s1[i]!=s2[i]) i++;k=s1[i]–s2[i];试以下面的具体输入情况说明上述程序段的处理过程。

1234ab 1234ABCD39已知执行下面的程序段前内存的情况

温馨提示

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

评论

0/150

提交评论