首页计算机计算机软件C语言程序设计 07 第6章 数组.pptx

07 第6章 数组.pptx

页数:73页文件大小:513.7 KB来源: C语言程序设计ppt课件

本课件从数组的定位讲起,依次展开一维数组的定义与元素引用、二维数组的定义与存储顺序、字符数组与字符串的概念及输入输出,并介绍常用的字符串处理函数;随后讲解数组名作函数参数的传递特点,最后通过排序与查找实例演示数组的应用。

第6章 数组,讲解的定义,数组元素的引用方法、掌握二维数组的定义、掌握字符数组与字符串的概念与定义方法,熟悉常等内容
6.1 数组概述,讲解编写程序的目的是处理数据、由程序处理的数据可能很简单等内容
和大多数高级语言一样,讲解C语言也采用了下面的数据机制、把语言要处理的数据对象划分为一些类型等内容
查看本课件的文字版(共 73 页,供检索与复制)

第1页:第6章 数组

第6章 数组

的定义,数组元素的引用方法。

2.掌握二维数组的定义,数组元素的引用,了解二维数组的实际意义。

3.掌握字符数组与字符串的概念与定义方法,熟悉常用的字符串处理函数。

4.掌握应用数组进行应用程序的设计的方法。

教学要求6.1概述6.3二维数组6.2一维数组6.6实例6.7小结结束6.5数组为函数的参数6.4字符数组和字符串

第2页:6.1 数组概述

6.1 数组概述

编写程序的目的是处理数据,前面我们已经提到,描述程序要处理的数据是程序设计很重要的一个方面。

由程序处理的数据可能很简单,也可能很复杂,为了描述各种各样不同的数据,要求语言系统有足够的数据表示能力。

第3页:和大多数高级语言一样

和大多数高级语言一样

提供一组基本数据类型,确定书写方式和一组相关基本操作,以支持程序中对基本数据对象的表示和使用。

提供一组由简单数据类型、数据对象构造更加复杂的数据类型、数据对象的手段,以满足程序中处理复杂数据的要求。

  • C语言也采用了下面的数据机制:
  • 把语言要处理的数据对象划分为一些类型,每个类型是一个数据值的集合。

第4页:复合数据对象

复合数据对象

利用C语言的数据构造技术,可把多个基本类型(或不是基本类型)的数据组成一个整体在程序中使用,这样能更贴切地描述现实问题中的数据。

  • C语言的基本类型包括整型、实型和字符类型,前面已经介绍了它们的表示和运算方面的问题。
  • C语言的构造类型包括数组、结构体和公用体,还有用于数据组织的重要机制“指针”。
  • 构造的数据对象(类型)是复合数据对象(类型)。
  • (类型)都有名字,其各个组成部分称为“元素”、“成员”和“成分”等。
  • 同时C语言提供访问复合对象成分的操作机制。

第5页:什么是数组

什么是数组

数组是C语言对一组相同性质数据的顺序存储管理机制;利用数组可把多个具有相同类型的数据对象组合在一起并作为一个整体来管理,这些数据对象称为数组的元素。

C语言中用a[0]、a[1]…的形式表示数组元素,[]中的整型数称为下标。使用下标和数组名可以用同一方式处理个别、一批或所有数组元素。

  • 数组是最简单的构造类型,但是十分有用,许多问题不用数组几乎难以解决。
  • 本章介绍一维和二维数组的定义、数组元素引用、字符数组。字符串和数组应用的基本算法。

第6页:6.1 数组概述

6.1 数组概述

  • 构造数据类型之一
  • 数组:有序数据的集合,用数组名标识。
  • 元素:属同一数据类型,用数组名和下标确定。

第7页:6.2 一维数组

6.2 一维数组

什么是一维数组数组的维数是指数组使用的下标个数,如果数组中每个元素只带有一个下标,称为一维数组。

定义形式类型说明符数组名[常量表达式];指出数组元素的数据类型。标识符必须用方括号括起来,指的是数组的元素个数(长度),是一个整型值,可包含常数和符号常量。

第8页:不能用变量定义数组维数;如

不能用变量定义数组维数;如

  • 不能用变量定义数组维数;如:intn=10;inta[n]
  • C语言规定,数组变量的大小是固定不变的,因此需要在定义时规定元素类型和元素个数。
  • 与普通变量一样,可以在一个定义语句中定义多个数组。如:inta[10],b[5],c

第9页:一维数组的存储掌握

一维数组的存储掌握

存储空间分配C语言系统定义数组时,根据定义语句中的空间需求分配足够的连续存储空间,数组元素顺序存放在这些存储单元中。

下标为0的元素排在最前面,每个元素占据的存储空间完全相同。

  • 一维数组在内存中的存储形式,有利于理解数组机制和数组元素的性质。
  • 数组空间开销计算有两种计算方法
  • 存储容量=元素个数×sizeof(元素类型名)
  • 存储容量=sizeof(数组名)

第10页:数组名的本质是数据组的内存起始地址

数组名的本质是数据组的内存起始地址

存储举例如:inta[5]内存字节数=元素个数*sizeof(元素类型)6.2一维数组a[0]0a[1]1a[2]2a[3]3a[4]4编译时分配连续内存数组名a表示内存首地址,是地址常量→a↘

scanf("%d",a); (非&a)将读入的一整数赋给a所表示的存储单元,该整型数正好是a的第一个数组元素的地址。
  • 可以把数组名看作是一个表示存储地址的常量。例如:如果a是已有定义的整型数组名,

第11页:一维数组的引

一维数组的引

引用数组元素的本质是将数组元素看作简单变量。数组元素可以作为定义类型的变量参加表达式计算和变量操作(引用和赋值)。

  • 用
  • 数组元素表示形式数组名[下标]其中:下标可以是常量或整型表达式
  • 说明
  • 数组必须先定义,后使用
  • 只能逐个引用数组元素,不能整体引用
  • 通过对下标变量的循环,可处理所有的元素

第12页:下标范围

下标范围

下标是元素相对于数组起始地址的偏移量,所以从0(下界)开始顺序编号。最后一个元素的下标(上界)值为数组元素个数减一。

注意:C语言系统并不自动检查数组的下标是否越界,对下标的控制由编称者完成。例:intdata[5];data[5]=10;//越界

  • 注意:元素的下标和元素在数组中的序号的关系,如a[i]表示数组a的第i+1个元素。

第13页:一维数组初始化

一维数组初始化

全部数组元素赋初值时,可不指定数组长度如:inta[]={1,2,3,4,5,6}6.2一维数组543210下标:654321a:

  • 初始化概念在定义数组时,为数组元素赋初值(在编译阶段使之得到初值)如:inta[6]={1,2,3,4,5,6}
  • a[0]=1;a[1]=2;a[2]=3;a[3]=4;a[4]=5;a[5]=6
  • 说明

第14页:可以只给部分数组元素赋初值如

可以只给部分数组元素赋初值如

a[0]=1;a[1]=2;a[2]=0;a[3]=0;a[4]=0;但:inta[3] ={1, 2, 3, 4};╳出界错误!

存储在静态存储区中(static、全局)数组元素不赋初值,系统会自动赋以0值如:staticinta[5]

a[0]=0;a[1]=0;a[2]=0;a[3]=0;a[4]=0;6.2一维数组43210下标:00021a:4321000000a:

  • inta[5]= { 1, 2 }
  • 默认值:
  • 存储在动态存储区中的(局部)数组不初始化,其元素值为随机数。

第15页:一维数组实例

一维数组实例

例1求一组成绩的平均分数,设给定的数据是87,90,85,98,65,80,74,67。

分析考虑用数组表示这组成绩,虽然给出的数据全是整数值,但考虑作为成绩及可能需要进行的运算,使用实型数更合适。

本例使用数组定义时初始化的方式来表示要计算的数据,其次,为增加程序的通用性,考虑让程序自动判断数据值的个数,用于循环结束的控制条件。

第16页:程序*

程序*

#include<stdio.h>main(){ inti,num; floatscore[]={ 87,90,85,98,65,80,74,67 } ; floatsum=0.0; num= sizeof(score)/sizeof(float); i<num; i++)sum+=score[i]; printf("Average:%.lf\n",sum/num);} 6.2一维数组运行结果:Average:

第17页:例2编写程序

例2编写程序

分析本例用循环结构控制数组的方法顺序或逆序地逐个引用数组元素的操作,实现换行动作的控制。

  • 将前15个奇数按每行5个的格式正序和反序输出。
  • 程序*

第18页:#defineM15main

#defineM15main

printf("SequenceOutput:\n"); for(i=0; i<M; i++){ printf("%4d",a[i]); if((i+1)%5==0)printf("\n"); } printf("InvertOutput:\n"); for(i=M-1; i>=0; i--){ printf("%4d",a[i]); if(i%5==0)printf("\n"); } } 6.2一维数组运行结果:Sequence Output:1 3 5 7 911 13 15 17 1921 23 25 27 29Invert Output:29 27 25 23 2119 17 15 13 119 7 5 3 1
  • (){inti,k=1,a[M];for(i=0;i<M;i++,k+=2)a[i]=k

第19页:例3编程

例3编程

比较第一个数与第二个数,若a[0]>a[1],则交换;

然后比较第二个数与第三个数;

依次类推,直至第n-1个数和第n个数比较为止。

(第一趟排序结果最大数在最后的位置上)

  • 输入一组整数,排序后由小到大输出。
  • 分析使用冒泡法来排序。其思路很简单,将相邻两个数组元素进行比较,将小的调整到前面。
  • 冒泡法排序过程
  • 对前n-1个数进行第二趟冒泡排序,结果使次大的数被安置在第n-1个元素位置
  • 重复上述过程,经n-1趟冒泡排序后,结束。

第20页:算法举例

算法举例

2一维数组2377148906682314770668第一趟第二趟14230668第三趟第四趟140623第五趟0614

第21页:程序*main

程序*main

(){inta[50],num,i,j,t,change=1;//change的作用?

printf("EnterNumbers:"); scanf("%d",&num); printf("EnterData:"); for(i=0; i<num; i++)scanf("%d",&a[i]); for(i=num-1; i>0&&change; i--){ change=0; for(j=0; j<i; j++)if(a[j]>a[j+1]){ t=a[j]; a[j]=a[j+1]; a[j+1]=t; change=1; } } printf("SortedData:"); for(i=0; i<num; i++)printf("%d",a[i]); } 6.2一维数组运行结果:Enter Numbers:5
  • Enter Data:23776148
  • Sorted Data:6 8 14 23 77

第22页:6.3 二维数组

6.3 二维数组

的定义形式类型说明符数组名[常量表达式1][常量表达式2];定义中除了使用两个方括号和常量表达式外,与一维数组的要求相同。

  • 的定义每个元素都带有两个下标的数组,称为二维数组。

第23页:对二维数组的理解

对二维数组的理解

也可把a看作一维数组,它有3个元素a[0]、a[1]、a[2],每个元素又是一个4元素一维数组:a[0]:a[0][0],a[0][1],a[0][2],a[0][3]a[1]:a[1][0],a[1][1],a[1][2],a[1][3]a[2]:a[2][0],a[2][1],a[2][2],a[2][3]

  • 看成是(常量式1×常量式2)的一个矩阵。
  • 也可看作一种特殊的一维数组,它的元素又是一维数组,即二维数组是数组的数组。
  • 例如:int a[3][4];定义了一个整型二维数组a。
  • 数组有12个元素,可看成为3行4列的矩阵

第24页:三维数组的实现

三维数组的实现

以二维数组为基础,如把维数组定义成元素是二维数组的数组。

下例定义了一个三维数组:floata[2][3][4]其元素是两个二维数组a[0]和a[1],都是一个3行4列的二维数组。

n维数组可以定义为n-1维数组的数组,如把n维数组a[t1][t2]…[tn]看成是由t1个n-1维数组组成的特殊一维数组,其元素a[0],a[1],…a[t1-1]都是t2×t3×…×tn的n-1维数组。

第25页:二维数组的存储

二维数组的存储

存储二维数组在内存中占据一系列连续的存储单元,数组元素按行顺序存放,先放行下标是0的元素,再放行下标是1的元素,依此类推。数组a[2][4]的存储示意图:

原因内存是一维的。

6.3二维数组a[1][3]a[1][2]a[1][1]a[1][0]a[0][3]a[0][2]a[0][1]a[0][0]←―行下标为1的元素―→←―行下标为0的元素―→

第26页:二维数组的引

二维数组的引

数组元素可以出现在表达式中,也可以被赋值。对基本数据类型的变量所能进行的操作,也都适合于相同数据类型的数组元素。

要注意数组引用和数组定义表示形式的区别。如:int a[3][4]表示数组的维数和各维数的大小,引用时a[3][4]代表数组元素,3和4是下标。

  • 用
  • 数组元素表示形式:数组名[下标1][下标2]其中:下标可以是常量或整型表达式
  • 说明
  • 每个下标的值不能超越该下标的上界和下界

第27页:二维数组的初始化

二维数组的初始化

二维数组定义时也可以用花括号对全部或前面一部分数组元素进行初始化。通过初始化可以定义二维数组。

部分初始化:inta[3][4]={{1,2},{3}};6.3二维数组032100040065002100030000321654

  • 初始化形式
  • 分行初始化
  • 全部初始化:inta[2][3]={{1,2,3},{4,5,6}}
  • 部分初始化:inta[3][4]={{1,2,3},{4},{5,6}}

第28页:按元素排列顺序初始化

按元素排列顺序初始化

初始化的数据多于数组的定义:inta[2][3]={1,2,3,4,5,6,7,8};×编译出错。

按元素排列顺序第一维长度省略:inta[][3]={1,2,3,4,5};6.3二维数组32165402100003210054000643210005

  • 全部:inta[2][3]={1,2,3,4,5,6}
  • 部分:inta[2][3]={1,2}
  • 第一维长度省略初始化
  • 分行第一维长度省略:inta[][4]={{1,2,3},{4,5},{6}}

第29页:二维数组实例

二维数组实例

分析遍历二维数组的每一个元素经常使用双重循环,本例演示了二维数组的基本输入输出控制方法。

  • 例5通过键盘给3×4的二维数组输入数据,然后分别按行和按列输出数组元素。
  • 程序*

第30页:main(){inta[3][4],i,

main(){inta[3][4],i,

Output by line:1 2 3 45 6 7 89 10 11 12Output by column:1 5 92 6 103 7 114 8 12

printf("Enterdatabyline:\n"); for(i=0; i<3; i++)for(j=0; j<4; j++)scanf("%d",&a[i][j]); printf("Outputbyline:\n"); for(i=0; i<3; i++){ for(j=0; j<4; j++)printf("%4d",a[i][j]); printf("\n"); } printf("Outputbycolumn:\n"); for(i=0; i<4; i++){ for(j=0; j<3; j++)printf("%4d",a[j][i]); printf("\n"); } } 6.3二维数组运行结果:Enter data by line:1 2 3 4 5 6 78 9 10 11 12
  • j;//调试时,输入数据用初始化

第31页:6.4 字符数组和字符串

6.4 字符数组和字符串

字符数组元素数据类型是字符类型的一维数组叫字符数组。如:charstr[50];定义了一个有50个字符的数组。

字符数组的引用字符数组的逐个字符引用与数值数组元素类似。54321olleH\0\0\0BA

  • 字符数组的初始化同一维数组
  • 逐个字符赋值:charc[5]={'H','e','l','l','o'}
  • 部分字符赋值:chars[5]={'A','B'}
  • 省略数组元素个数:chars[]={'1','2','3','4','5'}

第32页:字符串用双引号括起来的任意字符序列

字符串用双引号括起来的任意字符序列

结束标志'\0'代表ASCII码为0的字符,表示一个“空操作”,只起标志作用。

因此可以对字符数组采用另一种方式操作了──字符数组的整体操作。

6.4字符数组和字符串\05432154321

  • 包括字母、数字、专用字符、转义字符等。
  • 存储无字符串变量,用字符数组连续、顺序存放每一个字符,最后加字符'\0'做结束标志。
  • "12345"共5个字符,串长度5,占6个字节内存
  • chars[5]={'1','2','3','4','5'};占用5个字节的空间。

第33页:用字符数组处理字符串应考虑以下问题

用字符数组处理字符串应考虑以下问题

charstr[]={"China"};charstr[]="China";定义数组str的长度是6个字符。

charstr[5]="morning";×初始化的数据多于数组的定义,编译出错。6.4字符数组和字符串\0anihC\0\0\0\0\0anihC

  • 定义变量时,可能存储的最长字符串的长度。
  • 对字符数组初值赋值方法的扩充问题。
  • 例:
  • charstr[10]={"China"};str的前6个字符初始化,其他赋0。

第34页:字符串数组字符串数组就是数组

字符串数组字符串数组就是数组

存储利用C语言数组构造的特点,二维数组可以看作是一个一维数组,这个一维数组的元素又是一个一维数组。

因此,可以将一个二维字符数组看作一个字符串数组。

例如字符串数组line[10][80]共有10个元素,个元素可以存放80个字符(包括'\0')

  • 中的每一个元素都是存放字符串的数组。

第35页:字符串数组的初始化方法例

字符串数组的初始化方法例

引用可以通过二维数组元素的形式引用其中的字符。

如:上例中,str[1][1]的值是b。

6.4字符数组和字符串\0astr[0]\0bastr[1]\0cbastr[2]

  • charstr[3][5]={"a","ab","abc"};charstr[][5]={"a","ab","abc"}

第36页:字符串函数字符

字符串函数字符

与字符串是C程序处理的重要对象,C标准函数库中提供了许多相关的函数,它们的原型说明在下面头文件中:

  • ctype.h说明了一组字符类型判断函数
  • string.h说明了许多字符串处理函数
  • stdio.h说明了用于字符串I/O函数

第37页:常用的字符串函数

常用的字符串函数

  • 字符串输入输出函数(头文件:stdio.h)
  • scanf
  • printf
  • gets
  • puts
  • 字符串处理函数(头文件:string.h)
  • strcpy
  • strcat
  • strlen
  • strcmp
  • 字符判断函数(头文件:ctype.h)is…

第38页:字符串输入输出

字符串输入输出

输入项可以是串的起始地址,也可以是字符数组元素的地址,将从此地址表示的单元开始输入数据。如:

scanf("%s",str); 

第39页:printf的s格式串可以实现字符串

printf的s格式串可以实现字符串

字符数组操作的关键是理解数组名的地址属性,系统将数组名解释为地址常量,可以引用它定位数组的存储单元,但不能对数组名赋值。

printf("%s",str);
  • 的输出
  • 例如:charstr[20]
  • 功能:从str表示的地址开始输出存储单元中的字符,直到遇到第一个"\0"为止。
  • str也可以是字符数组元素的地址。

第40页:gets用于从终端输入字符串

gets用于从终端输入字符串

功能:从终端键盘读入字符串(包括空格),直到读入一个换行符为止。换行符不作为字符串的内容,系统自动加"\0"。

  • 调用形式:gets(str)
  • str是存放字符串的起始地址。可以是字符数组名、字符数组元素地址或字符指针。
  • 例如:gets(str);执行时键入以goodmorning!
  • 将读入该串并用"\0"替代最后的换行符(
  • )。

第41页:puts用于从终端输出字符串

puts用于从终端输出字符串

功能:str是输出字符串的起始地址,从这一地址开始,依次输出存储单元中的字符,直到遇到第一个"\0"为止,并自动输出一个换行符。6.4字符数组和字符串返回

puts(str);

第42页:字符串处理函数

字符串处理函数

例如:charstr[8];strcpy(str,"China");将常量串"China"复制到字符数组str中。

6.4字符数组和字符串\0anihCstr:

  • 字符串复制函数strcpy
  • 调用形式:strcpy(s1,s2)
  • 功能:把字符串s2复制到s1所指向的存储空间中,并返回s1的值。
  • s2是字符数组名或串常量,s1是字符数组名。
  • s1指向的存储空间必须足够容纳s2,复制时连同"\0"一起复制。

第43页:字符串连接函数strcat

字符串连接函数strcat

数组s1的空间必须足够容纳连接后的串。例如:chars1[20],s2[10];strcpy(s1,"like

");strcpy(s2,"school");stcat(s1,s2)6.4字符数组和字符串\0loohcsekils1:

  • 调用形式:strcat(s1,s2)
  • 功能:函数把字符串s2接到字符串s1的后面,自动覆盖s1后面的结束符,返回s1。

第44页:字符串长度函数strlen

字符串长度函数strlen

  • 调用形式:strlen(s)
  • 功能:函数用于计算并返回字符串s的长度,不包括末尾的结束符"\0"。
  • 例如:执行strcpy(str,"China");strlen(str)的值是5。

第45页:字符串比较函数strcmp

字符串比较函数strcmp

  • 调用形式:strcmp(s1,s2)
  • 功能:函数用于比较字符串s1和s2
  • 如果s1=s2,函数值返回0
  • 如果s1>s2,函数值返回正数
  • 如果s1<s2,函数值返回负数。
  • C语言中,字符串比较以字符比较为基础;字符比较等价于比较字符的ASCll编码
  • 两个字符比较有三种结果:等于、小于、大于。6.4字符数组和字符串返回

第46页:字符串比较规

字符串比较规

如果出现不同字符,则以第一个不同字符的比较结果为准。比较的结果由函数带回。因此,如果两个字符串相等,则它们不仅长度相同,而且对应位置的字符也相等。

  • 则:自左向右逐个字符比较,直到出现不同的字符或遇到'\0'为止。
  • 如果全部字符相同,则两字符串相等

第47页:字符判断函数isalpha

字符判断函数isalpha

(c)判断c是否为字母;isdigit(c)判断c是否为数字;isupper(c)判断c是否为大写字母。

  • 字符判断函数大部分是用宏实现的。
  • 返回值都是真值和假值,即非0和0。

第48页:合理地使用字符判断函数

合理地使用字符判断函数

比如程序中我们需要判断字符变量是否为数字字符,可以这样实现:if (c>=48 && c<=57)或if (c>='0' && c<='9')

若用判断函数if(isdigit(c));则程序与具体系统完全无关,在任何一个系统上运行都不需要进行修改。程序的可读性得到改善。

  • 可以改善程序的可移植性和可读性。
  • 这样的程序与具体的编码方案有关,要求使用的编码方案中数字字符的编码连续。
  • 本例采用ASCII方案,若不熟悉,很难理解,若要在其它方案的系统上运行,需修改。

第49页:字符数组和字符串实例

字符数组和字符串实例

main(){ charstr1[]="ChinaChina",str2[]="123",str3[]="abcd"; printf("str1=%o,str2=%o,str3=%o\n",str1,str2,str3); printf("Len1=%d,Len2=%d,Len3=%d\n",strlen(str1),strlen(str2),strlen(str3)); printf("str1=%s,str2=%s,str3=%s\n",str1,str2,str3); strcat(str3,str1); printf("str1=%s,str2=%s,str3=%s\n",str1,str2,str3); printf("Len1=%d,Len2=%d,Len3=%d\n",strlen(str1),strlen(str2),strlen(str3)); } 6.4字符数组和字符串…\0anihCanihC\0321\0dcbastr1str2str3
  • 例6.7*分析下面程序的运行结果。

第50页:6.4 字符数组和字符串内存情况

6.4 字符数组和字符串内存情况

str1str2str3…\0anihCanihC\0321\0dcba串连接后的内存情况:…\0anihCanihC\0321\0dcbastr1str2str3VC的内存分配从被4整除的字节开始。

运行结果:str1=6177474, str2=6177470, str3=6177460Len1=10, Len2=3, Len3=4str1=ChinaChina, str2=123, str3= abcdstrl=na, str2=aChina, str3=abcdChinahinaLen1=2, Len2=6, Len3=14本例说明:字符数组下标越界问题可能带来的影响!\0anihCanihC\0anihCanihC

第51页:例8*编写strcopy

例8*编写strcopy

#include<stdio.h>voidstrcopy(s1,s2)chars1[],s2[]; { inti=0; while(s2[i]!='\0'){ s1[i]=s2[i]; i++; } s1[i]='\0'; } main(){ charstr1[20],str2[6]="China"; strcopy(str1,str2); puts(str1); } 6.4字符数组和字符串函数可修改为:voidstrcopy(s1,s2)chars1[],s2[]; { inti=0; while(s1[i]=s2[i])i++;}
  • (s1,s2),完成字符串的复制操作。

第52页:6.5 数组作为函数的参数函数

6.5 数组作为函数的参数函数

是C语言中处理复杂问题的重要机制,但C语言函数实参和形参的结合只有值传递一种方式。对于数组对象,也有如何定义函数处理数组的问题。一、利用全局数组传递参数

数组名写在函数里面,只能处理某个固定的全局数组,函数依赖于这个数组,不能用同一个函数去处理别的数组以解决同样的问题。

  • 可以利用全局变量将要处理的数组定义成全局数组,使每一个函数都能操作需要的数组。

第53页:数组元素作函数参数—值传递

数组元素作函数参数—值传递

实参中的数组名是地址常量,因此,函数对应的形参应该是一个表示地址的对象(如指针变量,数组名)。6.5数组作为函数的参数

  • 与处理基本类型的变量一样
  • 只能个别地处理数组元素三、用数组名作函数的参数—地址值传递
  • 可在函数里处理整个数组的数据,也可通过不同调用完成同一函数对不同数组的相同计算。
  • 函数参数依然是值传递,只是该值为地址。

第54页:函数形参中

函数形参中

用数组名作函数参数,实参、形参传递的是数组名表示的地址值(依然是值传递)。

因此,实参和形参数组操作的是同一片空间。

形参数组操作可以改变实参数组元素的值。

这是用数组作参数和用简单变量作参数最大的不同。

6.5数组作为函数的参数

  • 数组名作形参的表示方法为:func( inta[ ])
  • 括号中不需要有元素个数,因为C系统都它们处理成int*指针形式,与元素个数无关。
  • 这里我们只要记住用类似inta[]这样的形式定义形参数组就可以了。

第55页:*:数组元素作函数参数#include<

*:数组元素作函数参数#include<

stdio.h>voidswap1(intx,inty){intz;z=x;x=y;y=z;}

swap1:z:12a[0]:a[1]:21x:y:运行结果:a[0]=1a[1]=2

main(){ inta[2]={ 1,2 } ; swap1(a[0],a[1]); printf("a[0]=%d\n",a[0]); printf("a[1]=%d\n",a[1]); } 6.5数组作为函数的参数
  • 调用前:12a[0]:a[1]:
  • 调用结束:12a[0]:a[1]:
  • 调用:12a[0]:a[1]:12x:y:

第56页:*:数组名作函数参数#include

*:数组名作函数参数#include<s

tdio.h>voidswap2(intx[]){intz;z=x[0];x[0]=x[1];x[1]=z;}

main(){ inta[2]={ 1,2 } ; swap2(a); printf("a[0]=%d\n",a[0]); printf("a[1]=%d\n",a[1]); } 6.5数组作为函数的参数12a→
  • 调用前:
  • swap2:x21a→21a→
  • 调用结束:
  • 调用:x12a→运行结果:a[0]=2a[1]=1

第57页:实参数组和形参数组的类型必须一致

实参数组和形参数组的类型必须一致

如果需要在函数中知道处理元素的个数,可以另设一个表示元素个数的参数。

例9修改例3的程序,把冒泡排序作为一个函数抽象出来,这样可适应对不同数组的排序要求。

程序如下*:6.5数组作为函数的参数

第58页:#include

#include

main(){ inti,j,num,a[50]; printf("EnterNumber:"); scanf("%d",&num); printf("EnterData:"); for(i=0; i<num; i++)scanf("%d",&a[i]); sort(a,num); printf("Sorteddata:"); for(i=0; i<num; i++)printf("%d",a[i]); } 6.5数组作为函数的参数voidsort(inta[],intnum){ intchange=1,t,i,j; for(i=num-1; i>0&&change; i--){ change=0; for(j=0; j<i; j++)if(a[j]>a[j+1]){ t=a[j]; a[j]=a[j+1]; a[j+1]=t; change=1; } } }
  • <stdio.h>voidsort(inta[],intnum )

第59页:6.6 实例

6.6 实例

例10将字符串转换成等值的机内数。体会字面量到机内表示的转换过程。将无符号八进制数串转换成十进制机内数。如:0556→366

  • 分析
  • 由变换:556=5×8×8+5×8+6=(5×8+5)×8+6
  • 得出计算中有一个累加过程,转换方法是:
  • 从高位起,累加值=累加值×8+本位值。
  • 用一维数组表示八进制数串。

第60页:程序*

程序*

#include<stdio.h>main(){ inti,n; chars[8]; printf("输入八进制整数:"); gets(s); i=0; n=0; while( s[i] != '\0' &&s[i]>='0' && s[i]<'8')n=n*8+s[i++]-'0'; if(s[i])printf("不是八进制数!\n"); elseprintf("换成的十进制数:%d\n",n); } 6.6实例运行结果:输入八进制整数:567
  • 换成的十进制数: 375输入八进制整数:678
  • 不是八进制数!

第61页:以10为例

以10为例

#include<stdio.h>main(){ inti=0,d,m,n; chars[8]; scanf("%d",&n); do{ m=n/8; d=n%8; s[i++]='0'+d; n=m; } while(n!=0); for(i--; i>=0; i--)putchar(s[i]); } 

第62页:例12计算一元多项式的值

例12计算一元多项式的值

变量设置:a:存放多项式的系数的数组;n:表示多项式最高次的幂值的常量;x:放指定点的值的变量;sum:存放累加和;t:是用于计算每一项的临时变量。

  • 用数组表示系数。f(x)=anxn+an-1xn-1+…+a1x1+a0
  • 方法1
  • 分别求出各个项的值,将结果累加。

第63页:程序:由双重循环实现for

程序:由双重循环实现for

(sum=0.0,i=0;i<N;i++){for(t=1.0,j=1;j<=i;j++)t=t*x;sum+=a[i]*t;}

改进:这段程序中有许多重复的计算,计算每个项的值时,总是从头开始作累乘。

如果能把前一次内部循环计算得到的t用于后一次计算,一次累乘就够了。

整个大循环可修改为一个单层循环。

sum=0.0;t=1.0;for(i=0;i<=N;i++){sum+=a[i]*t;t=t*x;}

第64页:方法2

方法2

应用数学知识,将多项式变形。

上面的多项式可以变形如下:f(x)=anxn+an-1xn-1+…+a1x1+a0=((…((anx+an-1)x+an-2)x+…+a2)x+a1)x+a0

  • 按上式,循环可以写为:sum=0.0;for(i=N;i>=0;i--)sum=sum*x+a[i]
  • 完整程序练习!6.6实例可以看到:几乎所有的数组问题都用到循环!

第65页:排序和查找

排序和查找

  • 例13用选择法排序。
  • 方法:设有n个元素,a[0],a[1],…,a[n-1]
  • 第一次,从a[0]~a[n-1]中选出最小的元素a[min],将a[0]与a[min]交换,在a[0]中得到最小元素
  • 第二次,从a[1]~a[n-1]中选出最小的元素a[min],将a[1]与a[min]交换
  • …
  • 依次类推,执行n-1次选择和交换后,将会得到有序数组。

第66页:程序*

程序*

#include<stdio.h>voidsort_sele(inta[],int); main(){ inti,n,a[50]; printf("EnterNum:"); scanf("%d",&n); printf("Enterdata:\n"); for(i=0; i<=n-1; i++)scanf("%d",&a[i]); sort_sele(a,n); for(i=0; i<=n-1; i++)printf("%5d",a[i]); } 6.6实例voidsort_sele(a, n)inta[], n; { inti, j, min, temp; for(i=0; i<=n-1; i++){ min=i; for(j=i+1; j<n; j++)if(a[min] >a[j])min = j; if(i!= min){ temp = a[i]; a[i] = a[min]; a[min]= temp; } } }

第67页:例14编写一个函数

例14编写一个函数

  • 将一个整数插入上题已排序好的表中。
  • 分析:设函数名为insert
  • 插入操作需知道:
  • 有序表名字
  • 元素的个数
  • 插入数据
  • 函数应返回:插入元素的插入位置。
  • 调用函数后:表中的元素个数增加1。
  • 方法:插入方法分三步
  • 第一步,找插入位置
  • 第二步,后移元素移出插入空位
  • 第三步,插入元素。

第68页:程序*intinsert

程序*intinsert

(a,num,in)inta[],num,in;{inti;for(i=num;i>0;i--){if(a[i-1]>in)a[i]=a[i-1];elsebreak;}a[i]=in;returni;}//考虑表中值不能相同

main()//只是简单调用{ inta[50]={ 2,4,6,8 } ; inti,x,n=4; printf("插入前:"); for(i=0; i<=n-1; i++)printf("%3d",a[i]); insert(a,n++,5); printf("\n插入后:"); for(i=0; i<=n-1; i++)printf("%3d",a[i]); } 6.6实例运行结果:插入前:2 4 6 8插入后:2 4 5 6 8

第69页:例15设有一整型数k

例15设有一整型数k

i=n找不到;以上例13、例14和例15三个例子是对线性表的排序、插入和修改的操作过程。

  • 在有序数组a中,找到与k相等的数,打印下标;找不到则打印信息。
  • 程序的中心语句:for(i=0;a[i]!=k&&i<n;i++)
  • 其余程序请大家自己完成
  • 注意循环结束时i的值与查找结果的关系:
  • i<ni为要打印的下标

第70页:字符串和字符数组的应用例16

字符串和字符数组的应用例16

方法定义查找函数,形参为字符串str和s;

函数从str的第一个字符开始,比较从此字符开始的字符串是否与s相同,若相同,返回该字符的位置,若不同,从str的下一个字符开始继续这个过程,如果str中没有与s相同的子串,返回-1。

  • 字符串查找的实现(术语叫模式匹配)
  • 功能从字符串对str中查找子串s,找到则报告第一个字符的位置;找不到,打印信息。

第71页:程序*

程序*

#include<string.h>intfind(char*,char*); main(){ charstr[50],s[10]; intre; printf("输入主串:"); gets(str); printf("输入子串:"); gets(s); re=find(str,s); printf("结果:%d",re); } 6.6实例intfind (charstr[],chars[]){ inti= 0, j, lm, ls; lm=strlen(str); for(j=0; j<ls; j++)if(str[i+j] !=s[j]){ i++; break; } if(j==ls)returni; } if(i>lm-ls)return-1; }

第72页:综合实例(略)例17设计一个类似于打字练

综合实例(略)例17设计一个类似于打字练

习的游戏程序。

游戏中不断地有字符从屏幕的顶部落下,在字符下落的过程中,用户键人相同字符,下落的字符即消失,对应位置的屏幕顶部产生新的字符,继续下落的过程。

如果某一个字符落到屏幕底部,统计这些字母的个数。

落底的字符数达到40个或用户键入回车符时游戏结束。

游戏允许用户选择屏幕上同时下落的字符数和下落速度。

  • 方法:为了减少参数,函数使用一组全局变量。采用多文件组织程序,源程序分为两个文件。
  • 程序练习

第73页:6.7 小结

6.7 小结

数组的基本概念。

包括数组定义、数组类型、数组维数、数组存储、数组元素和数组下标概念、数组说明、初始化方法、数组元素下标的范围、正确引用数组中的元素、数组元素的输入和输出方法、多维数组元素的排列方法和初始化等问题。

字符型数组。字符型数组与其他数组的区别,字符串及其特点,字符型数组初始化,使用不同的库函数输入输出字符串,对字符串的简单处理。

  • 数组与函数间的关系。包括数组名作函数参数,数组元素作函数参数,在函数中使用全局数组。
  • 常见的使用数组的算法。