目录 第八章 数组 1 简单学生成绩管理系统的开发 2 一维数组 3 多维数组 4 字符数组 5 数组作函数参数.

Slides:



Advertisements
Similar presentations
第 8 章 数组 计算机科学学院 李淮 Tel QQ
Advertisements

第一章 C语言概述.
《C语言程序设计》复习
电子成绩单项目实现.
第九章 字串 (String).
计算机硕士专业基础—C语言 赵海英
4.3 使用二维数组 P 求两个矩阵的和 求方阵对角线上元素之和 显示算术题和学生答题信息
C语言基础——指针的高级应用 Week 05.
第九章 指针 目录 指针与指针变量的概念 变量的指针和指向变量的指针变量 数组的指针和指向数组的指针变量
C语言程序设计 第八章 函数.
C语言程序设计 第十二章 位运算.
第5章 函数与模块化设计 学习目的与要求: 掌握函数的定义及调用方法 理解并掌握参数的传递方法 理解函数的嵌套与递归调用
第六章 数 组 主讲教师 贾月乐 联系电话:
高级语言程序设计 主讲人:陈玉华.
第5章 函数与预处理 《 C语言程序设计》 (Visual C++ 6.0环境) 本章导读
由C程序结构所知,一个完整的C语言程序是由一个且只能有一个main()函数(又称主函数)和若干个其他函数组合而成的。而前面各章仅学习main()函数的编程,本章将介绍其他函数的编程,包括其他函数的定义、调用、参数传递及变量的作用域等。
循环结构又称为重复结构:用来处理需要重复处理的问题,它是程序中一种很重要的结构。
選擇排序法 通訊一甲 B 楊穎穆.
Introduction to the C Programming Language
Chap 10 函数与程序结构 10.1 函数的组织 10.2 递归函数 10.3 宏定义 10.4 编译预处理.
项目六 用指针优化学生成绩排名 项目要求 项目分析
C程序设计.
第五章 选择结构程序设计 一、关系运算符和表达式 1、关系运算符 在程序中经常需要比较两个量的大小关系, 以决定程序下一步
Introduction to the C Programming Language
Introduction to the C Programming Language
第七章 函数 目录 有参的加法函数的开发 函数定义的一般形式 函数参数和函数的值 函数的调用
QQ: 李祥 QQ: 欢迎多种方式的学习交流,祝大家学有所成.
计算概论 第十八讲 C语言高级编程 结构与习题课 北京大学信息学院.
Introduction to the C Programming Language
Chap 8 指针 8.1 寻找保险箱密码 8.2 角色互换 8.3 冒泡排序 8.4 电码加密 8.5 任意个整数求和*
第八章 函数.
6.4.1指针与二维数组 1、二维数组结构的分析 设有数组定义为:int a[3][4]; 则有: a表示数组在内存中的首地址。
算法的基本概念.
C语言 程序设计基础与试验 刘新国、2012年秋.
第13章 结构体的应用 13.1 了解由用户构造的数据类型 13.2 结构体类型说明及结构体变量 13.3 结构体数组
第八章 使用指针.
函 数 实验八 第24讲 C程序设计 Main() { int x,y; X=10; y=x*x+1;
第三章 顺序结构程序设计 主讲教师 贾月乐 电话:
第5讲 结构化程序设计(Part II) 周水庚 2018年10月11日.
数组 梁春燕 华电信息管理教研室.
第1章 概述 本章要点: C语言程序结构和特点 C语言程序的基本符号与关键字 C语言程序的编辑及运行 学习方法建议:
C++大学基础教程 第5章 数组 北京科技大学 信息基础科学系.
第十章 用户自定义数据类型 目录 学生信息管理系统的开发 结构体数据类型的概述 结构体变量的使用 结构体数组
C语言概述 第一章.
C语言复习3----指针.
C语言大学实用教程 第6章 数组 西南财经大学经济信息工程学院 刘家芬
Main() { Dfas Asdfasf fasdfa } #include <stdio.h> void main( ) {
函数 概述 模块化程序设计 基本思想:将一个大的程序按功能分割成一些小模块, 特点: 开发方法: 自上向下,逐步分解,分而治之
函式庫補充資料.
C语言的特点 1. C程序由许多函数组成 2. C程序必须有且只有一个主函数main( ) 3. 函数用“{”和“}”表示起点和终点
7.1 C程序的结构 7.2 作用域和作用域规则 7.3 存储属性和生存期 7.4 变量的初始化
C程序设计.
C程序设计.
第4章 数 组.
資料結構與C++程式設計進階 遞迴(Recursion) 講師:林業峻 CSIE, NTU 6/ 17, 2010.
第九章 指针.
第2章 数据类型、运算符与表达式 本章要点: 基本数据类型 常量和变量 算术运算符和算术表达式 关系运算符和关系表达式
第2章 基本数据及其运算 本章学习的目标: 1、掌握基本数据的各种表示,基本数据常数的书写方法;
实验七 数 组 第21讲 C程序设计 Main() { int x,y; X=10; y=x*x+1;
程序设计基础.
Chap 7 数 组 7.1 排序问题 7.2 找出矩阵中最大值所在的位置 7.3 进制转换.
Introduction to the C Programming Language
C/C++基礎程式設計班 C語言入門、變數、基本處理與輸入輸出 講師:林業峻 CSIE, NTU 3/7, 2015.
第九章 指针 C程序设计中使用指针可以: 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 动态分配内存 得到多于一个的函数返回值.
C/C++基礎程式設計班 陣列 講師:林業峻 CSIE, NTU 3/14, 2015.
第三章 流程控制 程序的运行流程 选择结构语句 循环结构语句 主讲:李祥 时间:2015年10月.
陣列與檔案處理 授課:張朝麟 日期:2009/3/11.
台大資訊工程學系 資料系統訓練班 第119期 吳晉賢
C语言基础学习 从外行到入门.
Presentation transcript:

李祥 E-mail:tom_lx@126.com QQ:100756

目录 第八章 数组 1 简单学生成绩管理系统的开发 2 一维数组 3 多维数组 4 字符数组 5 数组作函数参数

知识点要求: 技能要求: 教学要求 1 字符数组的定义及引用 2 3 4 1 2 3 一维数组、多维数组的定义、初始化及使用 字符串处理函数 数组作函数参数 技能要求: 1 掌握数组在程序设计中的应用 2 掌握求数组元素最大值、排序等算法 3 理解数组名作函数参数

8.1 学生成绩管理系统的开发 任务描述: 开发一个简单的学生成绩管理系统,实现成绩的录入、平均分、最高分、排序与查询等功能。 任务要求: (1)设计一个菜单界面。 (2)编写inputScore函数,实现学生成绩的录入。 (3)编写averageScore函数,求学生成绩的平均值。 (4)编写maxScore函数,求所有成绩中的最高分。 (5)编写queryScore函数,实现学生成绩的查询。 (6)编写sortScore函数,将学生成绩按从高到低进行排序。

8.1 学生成绩管理系统的开发 任务分析: (1)菜单的设计,前面已学习过,请同学先自行完成。 (2)要存储多名学生的成绩,用用前面学过的变量来存储,需要定义大批量的变量,这样会使程序的编写变得复杂。 C语言中引入了一个重要的数据结构—数组,用于解决类似于学生成绩这样大批量的数据处理问题。 (3)所有对成绩的管理其实就是对数组元素进行处理。

8.1 学生成绩管理系统的开发 涉及知识点 一维数组的定义 一维数组元素的引用 数组元素的平均值、最大值 数组元素的排序

8.2 一维数组 8.2.1一维数组的定义 定义形式: type array_name[n]; 数组名的命名规则和变量名相同 如: 类型符,指每个 元素的数据类型 数组名 常量或常量表达 式,指元素个数 定义形式: type array_name[n]; 数组名的命名规则和变量名相同 如: int a[10]; //定义整型数组a具有10个元素 float b[5]; //定义浮点数数组b具有5个元素 char c[20] //定义字符数组c具有20个元素

8.2 一维数组 注意数组元素下标数值的起始: 如: int a[10]; 该数组有10个元素,它们如下: 下标从0开始 下标到9结束 … a[7] a[8] a[9] 下标从0开始 下标到9结束

8.2 一维数组 常见的错误: ① float a[0]; //数组大小为0没有意义 ② int b(2)(3); //不能使用圆括号 ③ int n=10, a[n]; //不能用变量说明数组大小

8.2 一维数组 2.一维数组在内存中的存放 一维数组: float mark[100]; mark[0] mark[1] mark[2] 86.5 92.0 77.5 52.0 94.0 低地址 高地址 每个数组元素占4个字节

8.2 一维数组 8.1.2 一维数组的初始化 数组的初始化: 在定义数组时直接给数组元素赋初值。 初始化方法: 从数组的第一个元素开始依次给出初始值表,表中各值之间用逗号分开,并用一对花括号将它们括起来。

根据花括号内元素个数系统自动确定中括号内省略的数值为10 8.2 一维数组 根据花括号内元素个数系统自动确定中括号内省略的数值为10 数组初始化的几种不种形式: 1)对全部数组元素赋予初值。如: int ndigit[10]={0,1,2,3,4,5,6,7,8,9}; 等价于: int ndigit[ ]={0,1,2,3,4,5,6,7,8,9}; 经上述初始化后,数组ndigit中的10个元素即ndigit[0]到ndigit[9]的值分别是0到9。 13-15 11.29

8.2 一维数组 数组初始化的几种不种形式: 2)对数组部分元素赋予初值。如: int fibonacci[20]={0,1}; 这样数组中的前两个元素为0、1,而后18个元素皆为0。 3)数组元素初值都为0,可写成: int a[10]={0}; 等价于: int a[10]={0,0,0,0,0,0,0,0,0,0};

8.2 一维数组 4)字符数组的初始化,可用字符串来代替。如: char pattern[ ]= “the”; //数组大小为4 等同于: 不等同: char pattern[]={‘t’, ‘h’, ‘e’, }; //数组大小为3 注意:在对字符数组初始化时,为使程序能觉察到数组中存放的字符串的末尾,在内部表示中,编译程序要用'\0'来结束这个数组,也就是说字符'\0'是字符串的结束标志,它的ASCII码为0,输出时无内容。从而存储的长度比双引号之间的字符的个数多一个。 10-12 11.29

8.2 一维数组 8.1.3 一维数组元素的引用 引用方式: 数组名[下标] 例如先定义一个一维整型数组a有10个元素: 整型常量或 整型表达式 引用方式: 数组名[下标] 例如先定义一个一维整型数组a有10个元素: int a[10]; 然后对每一个元素即可引用,如: a[1]= 5; a[6]=a[1]+9; printf("%d" , a[6]);

8.2 一维数组 注意: 在定义数组并对其中各元素赋值后,就可以引用数组中的元素 只能引用数组元素而不能一次整体调用整个数组全部元素的值。 在引用一个数组元素前应该让该数组元素有确定值,否则引用会得到不确定的数据结果。

【例8.1】从键盘输入5个整数,保存到数组a中,再逆序输出。 void main() {int a0,a1,a2,a3,a4; scanf(“%d”,&a0); scanf(“%d”,&a1); scanf(“%d”,&a2); scanf(“%d”,&a3); scanf(“%d”,&a4); printf(“%d\n”,a4); printf(“%d\n”,a3); printf(“%d\n”,a2); printf(“%d\n”,a1); printf(“%d\n”,a0); } void main() { int a[5]; scanf(“%d”,&a[0]); scanf(“%d”,&a[1]); scanf(“%d”,&a[2]); scanf(“%d”,&a[3]); scanf(“%d”,&a[4]); printf(“%d\n”,a[4]); printf(“%d\n”,a[3]); printf(“%d\n”,a[2]); printf(“%d\n”,a[1]); printf(“%d\n”,a[0]); }

void main() {int a0,a1,a2,a3,a4; scanf(“%d”,&a0); scanf(“%d”,&a1); scanf(“%d”,&a2); scanf(“%d”,&a3); scanf(“%d”,&a4); printf(“%d\n”,a4); printf(“%d\n”,a3); printf(“%d\n”,a2); printf(“%d\n”,a1); printf(“%d\n”,a0); } void main() {int i, a[5]; for(i=0;i<5;i++) scanf(“%d”,&a[i]); for(i=4;i>=0;i--) printf(“%d”,a[i]); }

8.2 一维数组 【例8.2】 求斐波那契数列中前20个元素的值。 Fibonacci 数列公式: 已知: f0 = 0 f1 = 1 fn = fn-1 + fn-2 即:0, 1 , 1 , 2 , 3 , 5 , 8 , 13 ……

8.2 一维数组 解题思路: 用简单变量处理,不能在内存中保存这些数。 用数组处理,每个数组元素代表数列中的一个数,依次求出各数并存放在相应的数组元素中。 斐波那契数列可以表示成“F0,F1,F2,…”,其中除F0和F1以外,其他元素的值都是它们前两个元素值之和,即Fn=Fn-2+Fn-1,而F0、F1分别为0和1,这里的0、1、2…即对应数组元素的下标。为此,在程序中说明整型数组fibonacci[20],并依次存放斐波那契数列的前20个元素值。

#include <stdio.h> void main( ) { int fibonacci[20],m,n; fibonacci[0]= 0; fibonacci[1]= 1; for(n=2;n<20;n++) fibonacci[n]=fibonacci[n-2]+fibonacci[n-1]; for(m=0;m<4;++m) //保证按4行输出 for(n=0;n<5;++n) //保证按一行输出5个数据 printf("%-6d",fibonacci[m*5+n]); //每个数据占6列,左靠齐 printf("\n"); //一行输出5个数据后换行 } return ;

8.2 一维数组 练习 完成学生成绩管理系统中主菜单函数和inputScore函数、averageScore函数的编写。 提示: (1)学生人数使用宏来定义,这样便于根据实际情况修改学生的人数。 (2)用一维数组来存储学生的成绩。 (3)由于inputScore函数、averageScore函数都将使用该数组,因此可将一维数组定义为全局变量。

8.2 一维数组 【例8.3】 求一维数组中所有元素的最大值及该元素的下标。 解题思路: 采用“打擂台算法” 先找出任一人站在台上,第2人上去与之比武,胜者留在台上 第3人与台上的人比武,胜者留台上,败者下台 以后每一个人都是与当时留在台上的人比武,直到所有人都上台比为止,最后留在台上的是冠军

8.2 一维数组 【例8.3】 求一维数组(共10个元素)中所有元素的最小值及该元素的下标。 解题思路: 采用“打擂台算法” 先把a[0]的值赋给变量max max用来存放当前已知的最大值 a[1]与max比较,如果a[1]>max,则表示a[1]是已经比过的数据中值最大的,把它的值赋给max,取代了max的原值 以后依此处理,最后max就是最大的值

8.2 一维数组 for i=1 to 9 max=a[i] k=i a[i]>max 真 max=a[0] 输出:max,k 假

8.2 一维数组 记行号 记最大值 练习:完成maxScore函数的编写。 …… int i, k=0,max; int a[10]={1,5,3,7,8,9,-2,4,1,-1}; max=a[0]; for (i=1;i<=9;i++) if (a[i]>max) { max=a[i]; k=i;} printf("max=%d\nk=%d\n",max,k); 记行号 练习:完成maxScore函数的编写。 记最大值

8.2 一维数组 【例8.4】从键盘任意输入10个数,按从小到大的顺序重新排列,然后输出。 对数排序的方法有多种,在这介绍两种: 冒泡法排序 选择法排序

8.2 一维数组 方法一:冒泡法(从小到大) 算法总体思想: 将每相邻的两个数进行两两比较,将小的数调到前面。 具体步骤见如下实例:

for(i=0;i<5;i++) if (a[i]>a[i+1]) { t=a[i];a[i]=a[i+1];a[i+1]=t; } a[0] a[1] a[2] a[3] a[4] a[5] 9 8 5 4 2 8 9 5 4 2 8 5 9 4 2 8 5 4 9 2 8 5 4 2 9 8 5 4 2 9 大数沉淀,小数起泡

for(i=0;i<4;i++) if (a[i]>a[i+1]) { t=a[i];a[i]=a[i+1];a[i+1]=t; } a[0] a[1] a[2] a[3] a[4] a[5] 8 5 4 2 9 5 8 4 2 9 5 4 8 2 9 5 4 2 8 9 5 4 2 8 9

for(i=0;i<3;i++) if (a[i]>a[i+1]) { t=a[i];a[i]=a[i+1];a[i+1]=t; } a[0] a[1] a[2] a[3] a[4] a[5] 5 4 2 8 9 4 5 2 8 9 4 2 5 8 9 4 2 5 8 9

for(i=0;i<2;i++) if (a[i]>a[i+1]) { t=a[i];a[i]=a[i+1];a[i+1]=t; } a[0] a[1] a[2] a[3] a[4] a[5] 4 2 5 8 9 2 4 5 8 9 2 4 5 8 9

for(i=0;i<1;i++) if (a[i]>a[i+1]) { t=a[i];a[i]=a[i+1];a[i+1]=t; } 2 4 5 8 9 a[0] a[1] a[2] a[3] a[4] a[5] 2 4 5 8 9

…… for(i=0;i<5;i++) if (a[i]>a[i+1]) { ……} for(i=0;i<4;i++) for(j=0;j<5;j++) for(i=0;i<5-j;i++) if (a[i]>a[i+1]) { ……} …… for(i=0;i<1;i++) if (a[i]>a[i+1]) { ……}

int a[10]; int i,j,t; printf("input 10 numbers :\n"); for (i=0;i<10;i++) scanf("%d",&a[i]); for(j=0;j<9;j++) for(i=0;i<9-j;i++) if (a[i]>a[i+1]) {t=a[i];a[i]=a[i+1];a[i+1]=t;} printf("the sorted numbers :\n"); for(i=0;i<10;i++) printf("%d ",a[i]); printf("\n");

8.2 一维数组 方法二:选择法 算法思想是:(考虑10 个数) 先将10个数中最小的数与a[0]对换;再将a[1]到a[9]中最小的数与a[1]对换……每比较一轮,找出一个未经排序的数中最小的一个 共比较9轮

a[0] a[1] a[2] a[3] a[4] 3 6 1 9 4 1 6 3 9 4 1 3 6 9 4 1 3 4 9 6 1 3 4 6 9 小到大排序

程序段如下: int i,j,k,t; for(i=0;i<n-1;i++) { k=i; for(j=i+1;j<n;j++) if(array[j]<array[k]) k=j; t=array[k]; array[k]=array[i]; array[i]=t; } 找最小值的下标

8.2 一维数组 练习: 选择一种排序算法,完成学生成绩管理系统中sortScore函数的编写。

8.2 一维数组 【例8.5】将十进制数转换成以指定数为基数的等值数。 解题思路: 指定基数的变化范围为2~16。 定义整型数组c存放变换结果,考虑到一些机器中以2为基数的长整数可达32位长度,与此相应的数组c的长度也被规定为32位。 数组c中存放转换结果,而且排列次序从低位到高位,在显示转换结果时则应从高位到低位。 在显示转换结果时,如果某一位的值在10~15范围内,则应显示英文字符’A’~’F’。 13-15 10-12 12.3

#include<stdio.h> void main() {int d,r,c[32],i=0; printf("请输入十进制数:"); scanf("%d",&d); printf("请输入要转换的进制:"); scanf("%d",&r); do {c[i]=d%r;i++; d=d/r;} while(d!=0); printf("转换以后的数是:"); for (i--;i>=0;i--) if (c[i]<=9) printf("%d",c[i]); Else printf("%c",c[i]+55); return ; }

8.2 一维数组 思考题: 题目:把一个整数依序插入已排序的数组中,设数组已按从小到大的顺序排列。 如:定义a数组并进行初始化。 int a[10]={2,4,6,8,10,12,16,18,20}; 要求:通过键盘输入一个数9,按顺序插入到 数组中,数组元素输出: 2,4,6,8,9,10,12,16,18,20

8.2 一维数组 练习: 完成queryScore函数的编写,实现学生成绩的查询。 任务要求: (1)从键盘录入要查询的成绩。 (2)若存在1个以上的数组元素和要查找的成绩相同,则只输出第一个找到的元素在数组中的下标。 (3)若没有成绩和要查找的成绩相同,则输出“没有找到”信息。

8.3 多维数组 项目改进:基于二维数组的多门课程成绩管理系统的开发 任务描述 编写inputScore2函数,实现固定数量学生的成绩录入。 任务要求: (1)为简单起见,本任务要求将学生数量固定为3个,课程数量固定为4门。 (2)录入时,要求可以逐个学生逐门课进行录入。

8.3 多维数组 项目改进:基于二维数组的多门课程成绩管理系统的开发 解题思路: (1)定义一个用于存放学生成绩的二维数组; (2)对于每个学生(外层循环),依次录入其4门课的成绩(内层循环)。 需解决的问题: 如何定义二维数组以及如何对二维数组进行遍历?

8.3 多维数组 任务实施 #include<stdio.h> int score[3][4]; void inputScore() { int i, j; //变量i代表行下标,j代表列下标 for(i = 0; i < 3; i ++) //遍历数组的每一行,依次处理每个学生 { printf("第%d个学生:\n", i+1); for(j = 0; j < 4; j++) { printf("输入第%d门课成绩:",j+1); scanf("%d", &score[ i ][ j ]); }

8.3 多维数组 二维数组的定义 类型说明符 数组名[常量表达式1][常量表达式2]; 如:int x[3][2]; 类型说明符 数组名[常量表达式1][常量表达式2]; 列数 数组类型 行数 如:int x[3][2]; 表示x是二维数组,它有3行2列,x数组中的每个元素都具有整数类型。 x[0][0] x[0][1] 第一行 x[1][0] x[1][1] 第二行 x[2][0] x[2][1] 第三行

8.3 多维数组 二维数组元素的引用形式: 数组名 [下标][下标] 如: int b[4][5]; b[1][2]= a[2][3]/2; 整型常量或 整型表达式 二维数组元素的引用形式: 数组名 [下标][下标] 如: int b[4][5]; b[1][2]= a[2][3]/2; 注意: 下标值不能超出定义的范围。

8.3 多维数组 ① 给全部元素赋初值 二维数组的初始化 类型说明符 数组名[常量1][常量2]={初始化数据}; a)分行赋初值 如:int y[3][4]={{1,3,5,7},{2,4,6,8},{3,5,7,9}}; b)不分行 如:int a[3][4]={1,3,5,7,2,4,6,8,3,5,7,9}; 第二维长度 不能省略! 1 3 5 7 2 4 6 8 3 5 7 9

8.3 多维数组 ② 给部分元素赋初值 二维数组的初始化 如:int y[4][3]={{1},{2},{3},{4}}; 1 0 0 0 5 6 0 0 0 0 0 0 1 0 0 0 6 0 0 0 11 0 0 0 1 0 0 2 0 0 3 0 0 4 0 0 int y[3][4] ={ {1},{5,6} }; 这些数据在内存中如何存放呢???

8.3 多维数组 二维数组元素在内存中的存储形式: 二维数组元素在内存中按行序优先存储,即当按照存储顺序存取元素时,最右边的下标变化最快 。 int a[3][4];

例如:int a[3][3]={ {1,2,3}, {4,5,6}, {7,8,9} }; 地址 值 数组元素 3000H 3002H 3004H 3006H 3008H 300AH 300CH 300EH 3010H a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2] a[2][0] a[2][1] a[2][2] 1 2 3 4 5 6 789

8.3 多维数组 注意:可把二维数组看作是一种特殊的一维数组:它的元素又是一个一维数组。 例如:int a[3][4]; a[0]、a[1]、a[2],每个元素又是一个包含4个元素的一维数组。

8.3 多维数组 三维数组的定义 如:int w[4][5][6]; 类型说明符 数组名[常量表达式1][常量表达式2][常量表达式2] 如:int w[4][5][6]; 定义w是三维数组,其各维长度分别是4、5、6,数组的下标也是最右边的先变。

8.3 多维数组 【例8.6】将年月日转换成一年中的第几天。 解题思路: 把某月某日转换为这年的第几天,要考虑该年是否为闰年,由于二月份的天数因闰年和非闰年而异。把每月的天数存放在数组day_tab[2][13],其中day_tab [0][1-12]是非闰年各月的天数,数组中[1][1-12]是闰年各月的天数。

【例8.6】程序代码 #include <stdio.h> day_of_year(int year, int month, int day) { int i,leap; static int day_tab[2][13]= {{0,31,28,31,30,31,30,31,31,30,31,30,31}, {0,31,29,31,30,31,30,31,31,30,31,30,31}}; leap=(year%4==0&&year%100!=0|| year%400==0); // 闰年时leap=1,否则leap=0 for(i=0;i<month;++i) day+=day_tab[leap][i]; return(day); }

printf("input year,month,day: "); 【例8.6】程序代码 void main( ) { int year,month,day; printf("input year,month,day: "); scanf("%d,%d,%d" ,&year,&month,&day); printf("%d\n" ,day_of_year(year,month,day)); return ; }

8.3 多维数组 思考: 将一个二维数组行和列元素互换,存到另一个二维数组中。 即行变列,列变行: 1 2 3 4 5 6 a= 1 4 2 5 3 6 b= 即行变列,列变行: a[i][j]→b[j][i] (0≤i<2 0≤j<3)

8.3 多维数组 二维数组使用说明: 二维数组可以较方便地处理矩阵数据。 通常把二维数组理解成一个具有多行(第一维数值决定行数),每行上又有多列(第二维决定列数)的一个二维矩阵阵列。 也可以把二维数组想象成是一个一维数组(元素的个数由第一维决定),每个元素又是一个包含有多个元素的一维数组(元素的个数由第二维决定)。 二维数组元素的引用通常与一个双重循环有关,外层循环用来控制访问行,内层循环用来控制访问列。

8.3 多维数组 项目完善: 开发一个基于二维数组的多门课程成绩管理系统,实现多个学生多门课程成绩的录入、平均分、最高分、查询等功能。 任务要求: (1)设计一个菜单界面。 (2)编写inputScore2函数,实现学生成绩的录入。(已实现) (3)编写averageScore2函数,可按用户要求计算某门课程的平均成绩或某个学生所有课程的平均成绩。 (4)编写maxScore2函数,求出所有成绩中最高分。(二维数组所有元素求最大值)

8.4 字符数组 8.3.1 字符数组的定义与引用 字符数组:用来存放字符的数组称为字符数组。 用一个一维字符数组可以存放一个字符串; 用一个二维字符数组可以存放多个字符串, 由于二维字符数组的每一个元素都是一个字符串,所以二维字符数组也称为字符串数组。

8.4 字符数组 字符数组定义的一般格式: char 数组名[字符串数量][字符串最大长度] 说明: [字符串数量]部分如果没有,则表示只定义了一个一维字符数组。 例如: char str[4][10]; str有4个字符串,分别是str[0]、str[1]、str[2]、str[3],每个字符串的最大长度为9个字符,每个字符串最后一个下标变量存放'\0',它是空字符,对应的ASCII码为0,输出无内容,代表字符串结束。

8.4 字符数组 字符数组的初始化: 字符数组的初始化可按行进行。例如: char str[4][10]={“Turbo C”, “Microsoft”, "FORTRANIV","PASCAL"}; 也可以使用赋值语句,例如给第一个字符串赋值: str[0][0]='T'; str[0][1]='u'; str[0][2]='r'; str[0][3]='b'; str[0][4]='o'; str[0][5]=' ';//空格字符 str[0][6]=‘C’; str[0][7]=‘\0’; 除初始化不允许对字符数组整体赋值。如下是错误的: str[0]="Turbo C";

8.4 字符数组 以下字符串的存放形式: char str[4][10]={“Turbo C”, “Microsoft”, "FORTRANIV","PASCAL"}; T u r b o c \0 M i s f t F O R A N I V P S C L

8.4 字符数组 8.3.2 字符串处理函数 1. puts函数 形式: puts (字符数组/字符串常量) 作用:将一个字符串(以'\0'结束的字符序列)输出到显示器。

8.4 字符数组 puts函数输出的字符串中可包含转义字符: 例如: static char str[]={"China\nBeijing″}; puts(str); 输出结果: China Beijing

8.4 字符数组 2. gets函数 形式:gets(字符数组) 作用:从终端输入一个字符串到字符数组,并且得到一个函数值,该函数值是字符数组的起始地址。函数调用如下: gets(str) 注意: 用puts和gets函数只能输入或输出一个字符串,不能写成: puts(str1,str2)或gets(str1,str2)。

8.4 字符数组 注意:使用以下字符串函数时,在程序开头用 #include <string.h> 3. strcat函数 作用:连接两个字符数组中的字符串,把字符串2接到字符串1的后面,结果放在字符数组1中,函数调用后得到一个函数值——字符数组1的地址。 13-15. 12.5

8.4 字符数组 例如: char str1[30]={″People’s Republic of ″}; 要足够大 例如: char str1[30]={″People’s Republic of ″}; char str2[]={″China″}; print(″%s″,strcat(str1,str2)); 输出: People′s Republic of China str1

8.4 字符数组 4. strcpy函数 形式:strcpy(字符数组1,字符数组2/字符串) 作用:将字符串2复制到字符数组1中。 例如: static char str1[10],str2[]={“ China”}; strcpy(str1,str2); 执行后,str1的内容与str2相同:

8.4 字符数组 关于strcpy函数,要注意以下几点: (1) 字符数组1必须定义得足够大,以便容纳被拷贝的字符串。字符数组1的长度不应小于字符串2的长度。 (2) 字符数组1必须写成数组名形式(如str1),“字符串2”可以是字符数组名,也可以是一个字符串常量。如 strcpy(str1, "China") (3) 拷贝时连同字符串后面的'\0'一起拷贝到字符数组1中。

8.4 字符数组 关于strcpy函数,要注意以下几点: (4) 不能用赋值语句将一个字符串常量或字符数组直接赋给一个字符数组。如下面的赋值是不合法的: str2={"China"}; str1=str2; 如果用赋值语句,只能将一个字符赋给一个字符型变量或字符数组元素。如下面是合法的: char a[4],c1; c1='A'; a[0]='C';a[1]='h';a[2]='i';

8.4 字符数组 关于strcpy函数,要注意以下几点: strcpy(str1,str2,2); 作用是将str2中前面2个字符拷贝到str1中去。

8.4 字符数组 5. strcmp函数 形式:strcmp (字符串1,字符串2) 作用:比较两个字符串的大小。 例如: strcmp(str1,str2); strcmp(″China″,″Korea″); strcmp(str1,″Beijing″);

8.4 字符数组 比较的结果由函数值带回: (1) 字符串1==字符串2,函数值为 0 ; (2) 字符串1>字符串2,函数值为 1 ; (3) 字符串1<字符串2,函数值为-1 。 注意:两个字符串比较,不能用以下形式: if(str1==str2) printf(″yes″); 只能用以下形式: if(strcmp(str1,str2)==0) printf(″yes″);

8.4 字符数组 6. strlen函数 形式:strlen (字符数组/字符串常量) 作用:测试字符串的长度。 函数值:字符串的实际字符个数(不包括′\0′)。如: static char str[10]={"China"}; printf("%d",strlen(str)); 输出结果不是10,也不是6,而是5。也可以直接测字符串常量的长度,如: strlen("China")

8.4 字符数组 7. strlwr函数 形式:strlwr (字符串) 作用:将字符串中大写字母换成小写字母。 8. strupr函数 作用:将字符串中小写字母换成大写字母。 10-12 12.4

8.4 字符数组 练习: 1.有一篇文章,共有3行文字,每行有80个字符,要求分别统计出其中英文大写字母、小写字母、数字、空格以及其他字符的个数。 2.从键盘输入一个字符串,删除其中的字母 a后输出。例如,输入字符串“abcaca”,输出 bcc。

8.5 数组作函数参数 数组作为函数参数时有两种形式: 数组元素作为函数的参数  数组名作为函数参数

8.5 数组作函数参数 8.5.1数组元素作函数参数 数组元素作为函数参数时,只是将该数组元素的值传给形参,以后形参的值有无变化和实参数组元素无关,即不影响实参数组元素,可以看作是一种单向传递。在使用时同普通变量作参数一样注意形参与实参类型的一致或兼容。

8.5 数组作函数参数 【例8.7】求部分数组元素的和 #include <stdio.h> int fun(int i,int j,int k) { int sum; sum=i+j+k; i++; //i变化不会影响实参a[1] j++; //j变化不会影响实参a[2] k++; //k变化不会影响实参a[3] return(sum); }

8.5 数组作函数参数 void main( ) { static int a[5]={1,3,5,7,9}; int y; y=fun(a[1],a[2],a[3]); //仅将a[1],a[2],a[3]的值传给形参i、j、k printf("%d\n" ,y); for (i=0;i<5;i++) printf("%d ",a[i]); return ; }

8.5 数组作函数参数 8.5.2 数组名作函数参数 数组名作函数参数时,是将实参数组的起始地址传递到被调函数对应的形参中,也就是说形参数组的起始地址和实参数组的起始地址是相同值,那么形参数组和实参数组就共用相同的存储空间,以后对形参数组元素的使用就是对实参数组元素的使用,即形参数组元素的变化会影响到实参数组元素,可以把这种传递看作是双向传递。

8.5 数组作函数参数 【例8.8】 有一个一维数组score,内放10个学生成绩,求平均成绩。 解题思路: (1)用函数average求平均成绩,用数组名作为函数实参,形参也用数组名 (2)在average函数中引用各数组元素,求平均成绩并返回main函数

#include <stdio.h> int main() { float average(float array[10]); float score[10],aver; int i; printf("input 10 scores:\n"); for(i=0;i<10;i++) scanf("%f",&score[i]); printf("\n"); aver=average(score); printf("%5.2f\n",aver); return 0; } 定义实参数组

定义形参数组 float average(float array[10]) { int i; float aver,sum=array[0]; for(i=1;i<10;i++) sum=sum+array[i]; aver=sum/10; return(aver); } 相当于score[0] 相当于score[i]

8.5 数组作函数参数 几点说明: 1、用数组名作函数参数,应该在主调函数和被调函数分别定义数组。 2、实参与形参类型必须一致,如不一致,则出错。 3、在定义average函数时,声明数组的大小为10,但在实际上,指定其大小是不起任何作用的。 4、形参数组可以不指定大小,在定义数组时在数组名后面跟一个空的方括号,可再设一个形参,传递数组元素的个数。

8.5 数组作函数参数 强调: 数组名作参数时,不是把数组元素的值传递给形参,而是把实参数组的起始地址传递给形参数组,这样两个数组共占同一段内存,这与变量做函数参数的情况不相同的。 score[0] score[1] score[2] score[3] score[4] score array array[2] array[4] array[0] array[1] array[3]

8.5 数组作函数参数 在实际应用中,实参也可以是数组中某元素的地址 【例8.9】用函数sum_array( )求n个数之和 int sum_array(int a[],int n) { int i,total; for(i=0,total=0;i<n;i++) total+=a[i]; return total; }

8.5 数组作函数参数 调用函数sum_array( ),如有以下变量定义: int x[]={1,2,3,4,5}; int i,j; 则语句: i=sum_array(x,5); j=sum_array(&x[2],3); printf("i=%d\nj=%d\n",i,j); 将输出: i=15 j=12

8.5 数组作函数参数 实参传递给形参(数组)的是数据表开始地址,函数对形参数组元素的访问就是对实参数组元素的访问。如有必要,函数可以改变实参数组元素的值。 如: void init_array(int a[],int n,int val) { int i; for(i=0;i<n;i++) a[i]=val; } 如有以下数组定义: int a[10],b[100]; 以下语句的功能? init_array(a,10,1); init_array(b,100,2); 网络工程 12.3

8.5 数组作函数参数 练习: 编写一个函数mystrcpy(),将一个字符串中的元音字母复制到另一个字符串,然后在主函数中输出。 题目分析: (1)定义两个字符数组分别用来存放原字符串和元音字母字符串。 (2)函数的原型为: void mystrcpy(char a[ ],char b[ ])

8.5 数组作函数参数 项目完善 将简单学生成绩管理系统中存放学生成绩的全局数组改用局部数组,改用数组名作函数参数的形式实现。

8.5 数组作函数参数 8.5.3 多维数组作函数参数 当形参数组是多维数组时,除形参数组的第一维大小说明可省略外,其他维的大小必须明确指定。

8.5 数组作函数参数 函数sumatob()用于求一个有10列的二维数组各行10个元素之和并存于另一个数组中。 void sumatob(int a[][10],int b[],int n) { int i,j; for(i=0;i<n;i++) for(b[i]=0,j=0;j<10;j++) b[i]+=a[i][j]; }

8.5 数组作函数参数 【例8.10】编写函数yanghui,输出如下杨辉三角形。 提示:杨辉三角形的特点是第i行有i个数字,每行的第一个、最后一个数均为1,其余每一个数正好等于它一行的同一列和前一列数之和。 函数的原型为:void yanghui(int a[][N])

8.5 数组作函数参数 项目改进 将基于二维数组的多门课程成绩管理系统中存放学生成绩的全局数组改用局部数组,改用多维数组作函数参数的形式实现。

重点: 难点: 本章小结 1 2 3 1 2 数组的定义及数组元素的使用 求数组元素的最大值、排序等算法 数组作为函数参数 字符数组的应用 数组作为函数的参数

本章结束!