Chap 11 指针进阶 11.1 奥运五环色 11.2 字符定位 11.3 用链表构建学生信息库.

Slides:



Advertisements
Similar presentations
第九章 指针 西安工程大学.
Advertisements

第七章 指针 计算机公共教学部.
第六章 指针 指针的概念 指针变量 指针与数组 指针与函数 返回指针值的函数.
第7章 指针 存储地址的变量的类型就是指针类型 能直接对内存地址操作, 实现动态存储管理 容易产生副作用, 初学者常会出错
第七章 指针 教 材: C程序设计导论 主 讲: 谭 成 予 武汉大学计算机学院.
电子成绩单项目实现.
二级指针与二维数组.
C语言程序设计基础 第10章 指针进阶 刘新国.
10.1 二级指针 10.2 指针与二维数组 10.3 指针的动态存储分配 10.4 函数指针 10.5 main函数的参数
第8章 指针 21世纪高等学校精品规划教材.
補充: Input from a text file
C语言程序设计.
第6章 指针 6.1 指针的概念 6.2 变量与指针 6.3 数组与指针 6.4 字符串与指针 6.5 函数与指针 6.6 返回指针值的函数
6.4 字符串与指针 1. 用字符数组存放一个字符串.
1.7.1 指针和指针变量 int i = 5; int *p = &i; C++中定义一个指针变量可按下列格式:
第六节 二维数组和指针 二维数组的地址 对于一维数组: (1)数组名array表示数组的首地址, 即array[0]的地址;
C++中的声音处理 在传统Turbo C环境中,如果想用C语言控制电脑发声,可以用Sound函数。在VC6.6环境中如果想控制电脑发声则采用Beep函数。原型为: Beep(频率,持续时间) , 单位毫秒 暂停程序执行使用Sleep函数 Sleep(持续时间), 单位毫秒 引用这两个函数时,必须包含头文件
第九章 字符串.
第九章 系 统 安 全 性 9.1 结构体 9.2 结构体型数组  9.3 结构体型指针 9.4 内存的动态分配 9.5 共用体
第6章 指针 学习目的与要求: 了解指针的概念和相关术语 熟练掌握指向变量、数组和字符串的指针变量的使用方法 了解指向函数的指针变量
指 针 为什么要使用指针 指针变量 指针与数组 返回指针值的函数 动态内存分配 通过指针引用字符串 指向函数的指针 小 结 习 题.
补充内容 结构体 概述 定义结构体类型和定义结构体变量 结构体变量的引用 结构体变量的初始化 指针与结构体 用typedef定义类型的别名.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
第八章 指 针 8.1 指针的概念与定义 8.2 指针作函数参数 8.3 指针与数组 8.4 指针与函数 8.5 复杂指针.
第 十 章 指 针.
C语言高级编程(第四部分) 字符串 北京大学 信息科学技术学院.
Chap 9 结构 9.1 构建手机通讯录 9.2 结构变量 9.3 结构数组 9.4 结构指针.
程序设计专题 第2讲 - 结构 刘新国.
STRUCTURE 授課:ANT 日期:2010/5/12.
计算概论 第十八讲 C语言高级编程 结构与习题课 北京大学信息学院.
Chap 11 指针进阶 11.1 布袋中的彩色球 11.2 解密藏头诗 11.3 学生信息管理的链表实现.
Chap 8 指针 8.1 寻找保险箱密码 8.2 角色互换 8.3 冒泡排序 8.4 电码加密 8.5 任意个整数求和*
C语言程序设计 李祥.
Chap 8 指针 8.1 寻找保险箱密码 8.2 狸猫换太子 8.3 冒泡排序 8.4 加密变换问题 8.5 任意个整数求和问题*
辅导课程六.
函数申明、定义、调用 申明: void sort(float a[], int n); void sort(float *a, int m); void sort(float *a, int); void sort(float *, int);
Zhao4zhong1 (赵中) C语言指针与汇编语言地址.
Zhao4zhong1 (赵中) C语言指针与汇编语言地址.
二维数组的指针表示 与复杂的指针例子 专题研讨课之三.
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
C语言 程序设计基础与试验 刘新国、2012年秋.
C语言程序设计基础 第8章 指针 刘新国.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
第8章 指针.
欲穷千里,更上层楼 第十章 指 针 指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构; 能很方便地使用数组和字符串; 并能象汇编语言一样处理内存地址,从而编出精练而高效的程序。指针极大地丰富了C语言的功能。 学习指针是学习C语言中最重要的一环,
第五章 习题课 电子信息与计算机科学系 曾庆尚.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
简单介绍 用C++实现简单的模板数据结构 ArrayList(数组, 类似std::vector)
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
C语言复习3----指针.
C语言大学实用教程 第7章 指针 西南财经大学经济信息工程学院 刘家芬
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
第6讲 指针与引用 6.1 指针 6.2 引用.
第 四 讲 线性表(二).
第4章 Excel电子表格制作软件 4.4 函数(一).
C qsort.
C程序设计.
3.16 枚举算法及其程序实现 ——数组的作用.
第8章 善于利用指针 8.1 指针是什么 8.2 指针变量 8.3 通过指针引用数组 8.4 通过指针引用字符串 8.5 指向函数的指针
函数申明、定义、调用 申明: void sort(float a[], int n); void sort(float *a, int m); void sort(float *a, int); void sort(float *, int);
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
C程序设计.
本节内容 C语言的汇编表示 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
实验目的:掌握数据的顺序存储结构及它们在计算机中的操作。 实验内容:
C++语言程序设计 C++语言程序设计 第一章 C++语言概述 第十一组 C++语言程序设计.
本节内容 动态链接库 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
C语言程序设计 第8章 指针.
第八章 指 针 北京邮电大学出版社.
本节内容 this指针 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
Presentation transcript:

Chap 11 指针进阶 11.1 奥运五环色 11.2 字符定位 11.3 用链表构建学生信息库

本章要点 指针数组和指向指针的指针是如何被定义和使用的? 指针如何作为函数的返回值? 指向函数的指针的意义是什么? 什么是结构的递归定义,哪种应用需要这种定义方法? 对链表这种数据结构,如何使用动态内存分配操作? 如何建立单向链表并实现插入、删除以及查找操作?

11.1 奥运五环色 11.1.1 程序解析 11.1.2 指针数组的概念 11.1.3 指向指针的指针 11.1 奥运五环色 11.1.1 程序解析 11.1.2 指针数组的概念 11.1.3 指向指针的指针 11.1.4 用指针数组处理多个字符串 *11.1.5 命令行参数

11.1.1 程序解析 【例11-1】已知奥运五环的5种颜色的英文单词按一定顺序排列,输入任意一个颜色的英文单词,从已有颜色中查找并输出该颜色的位置值,若没有找到,则输出“Not Found”。

11.1.1 程序解析 运行结果1 Input a color:yellow position:3 运行结果2 指针数组 11.1.1 程序解析 运行结果1 Input a color:yellow position:3 运行结果2 Input a color:purple Not Found #include<stdio.h> #include<string.h> int main(void) { int i; char *color[5] = {“red”, ”blue”, ”yellow”, ”green”, ”black” }; char str[20]; printf(“Input a color:”); scanf(“%s”, str); for(i = 0; i < 5; i++) if(strcmp(str, color[i]) == 0) /* 比较颜色是否相同 */ break; if(i < 5) printf(“position:%d\n”, i+1); else printf(“Not Found\n”); return 0; } 指针数组

11.1.2 指针数组的概念 C语言中的数组可以是任何类型,如果数组的各个元素都是指针类型,用于存放内存地址,那么这个数组就是指针数组。 11.1.2 指针数组的概念 C语言中的数组可以是任何类型,如果数组的各个元素都是指针类型,用于存放内存地址,那么这个数组就是指针数组。 一维指针数组定义的一般格式为: 类型名 *数组名[数组长度]

11.1.2 指针数组的概念 int a[10]; char *color[5]; a是一个数组,它有10个元素 每个元素的类型都是整型 11.1.2 指针数组的概念 int a[10]; a是一个数组,它有10个元素 每个元素的类型都是整型 char *color[5]; color是一个数组,它有5个元素 每个元素的类型都是字符指针

11.1.2 指针数组的概念 对指针数组元素的操作和对同类型指针变量的操作相同 11.1.2 指针数组的概念 char *color[5] = {"red", "blue", "yellow", "green", "black" }; color是一个数组,它有5个元素 每个元素的类型都是字符指针 数组元素可以处理字符串 对指针数组元素的操作: printf("%s %x\n", color[i], color[i]); 对指针数组元素的操作和对同类型指针变量的操作相同

11.1.2 指针数组的概念 继续执行: char * tmp; tmp = color[0]; color[0] = color[4]; 11.1.2 指针数组的概念 继续执行: char * tmp; tmp = color[0]; color[0] = color[4]; color[4] = tmp; color[0]与color[4]交换后的情况 指针数组操作时: 可以直接对数组元素进行赋值(地址值)和引用 tmp=color[0]; 也可以间接访问和操作数组元素所指向的单元内容 strcpy(color[0], “purple");

11.1.3 指向指针的指针 C语言中,指向指针的指针(二级指针)一般定义为: 类型名 **变量名 int **pp = &p; &a p 11.1.3 指向指针的指针 C语言中,指向指针的指针(二级指针)一般定义为: 类型名 **变量名 int a = 10; int *p = &a; int **pp = &p; &a p a 10 &p pp *p *pp **pp

【例11-2】 int a = 10, b = 20, t; int *pa = &a, *pb = &b, *pt; int **ppa = &pa, **ppb = &pb, **ppt; 【例11-2】 pa a ppa &a 10 &pb **ppb *pa &b pb b 20 &pa ppb **ppa *pb &a pa a 10 &pa ppa **ppa *pa &b pb b 20 &pb ppb **ppb *pb pa a ppa &b 10 &pb **ppa *pb &a pb b 20 &pa ppb **ppb *pa pa a ppa &b 20 &pb **ppa *pb &a pb b 10 &pa ppb **ppb *pa 操作(1):ppt = ppb; ppb = ppa; ppa = ppt; 操作(2):pt = pb; pb = pa; pa = pt; 操作(3):t = b; b = a; a = t;

11.1.3 指向指针的指针 【例11-3】改写例11-1,用指向指针的指针实现。 指向指针的指针 使用指向指针的指针 操作数据 11.1.3 指向指针的指针 【例11-3】改写例11-1,用指向指针的指针实现。 #include<stdio.h> #include<string.h> int main(void) { int i; char *color[5] = {“red”, ”blue”, ”yellow”, ”green”, ”black”}; / char **pc; /* 定义二级指针变量 */ char str[20]; pc = color; /* 二级指针赋值 */ printf(“Input a color:”); scanf(“%s”, str); for(i = 0; i < 5; i++) if(strcmp(str, *(pc+i)) == 0) /* 比较颜色是否相同 */ break; if(i < 5) printf(“position:%d\n”, i+1); else printf(“Not Found\n”); return 0; } 指向指针的指针 使用指向指针的指针 操作数据

11.1.3 指向指针的指针 【例11-3】改写例11-1,用指向指针的指针实现。 pc  color &color[0] 11.1.3 指向指针的指针 【例11-3】改写例11-1,用指向指针的指针实现。 pc  color &color[0] *pc  color[0] *(pc+i)color[i] **pc*(*pc)*color[0] : ‘r’

11.1.4 用指针数组处理多个字符串 1.指针数组与二维数组 指针数组 二维字符数组 11.1.4 用指针数组处理多个字符串 指针数组 char *pcolor[ ] = {"red", "blue", "yellow", "green", “black"}; 1.指针数组与二维数组 二维字符数组 char ccolor[ ][7] = {"red", "blue", "yellow", "green", “black"}; 使用指针数组更节省内存空间

11.1.4 用指针数组处理多个字符串 2.用指针数组操作多个字符串 【例11-4】将5个字符串从小到大排序后输出。 11.1.4 用指针数组处理多个字符串 2.用指针数组操作多个字符串 【例11-4】将5个字符串从小到大排序后输出。 #include <string.h> void main( ) { int i; char *pcolor[ ] ={ “red”, ”blue”, ”yellow”, ”green”, ”black”}; void fsort(char *color[ ], int n); fsort(pcolor, 5); for(i = 0; i < 5; i++) printf("%s ", pcolor[i]); } void main( ) { int i; int a[5] = {6, 5, 2, 8, 1}; void fsort(int a[ ], int n); fsort(a, 5); for(i = 0; i < 5; i++) printf("%d ", a[i]); }

11.1.4 用指针数组处理多个字符串 void fsort(char *color[ ], int n) { int k, j; 11.1.4 用指针数组处理多个字符串 void fsort(char *color[ ], int n) { int k, j; char *temp; for(k = 1; k < n; k++) for(j = 0; j < n-k; j++) if(strcmp(color[j],color[j+1])>0){ temp = color[j]; color[j] = color[j+1]; color[j+1] = temp; } void fsort(int a[ ], int n) { int k, j; int temp; for(k = 1; k < n; k++) for(j = 0; j < n-k; j++) if(a[j] > a[j+1]){ temp = a[j]; a[j] = a[j+1]; a[j+1] = temp; }

11.1.4 用指针数组处理多个字符串 排序前 排序后

11.1.4 用指针数组处理多个字符串 3.动态输入多个字符串 11.1.4 用指针数组处理多个字符串 3.动态输入多个字符串 例11-5 输入一些有关颜色的单词,每行一个,以#作为输入结束标志,再按输入的相反次序输出这些单词。其中单词数小于20,每个单词不超过15个字母(用动态分配内存的方法处理多个字符串的输入)。

采用动态分配内存的方法处理多个字符串的输入的优点在于,能够根据实际输入数据的多少来申请和分配内存空间,从而提高了内存的使用率。 #include <stdio.h> #include<stdlib.h> #include<string.h> int main(void) { int i, n = 0; char *color[20], str[15]; scanf("%s", str); while(str[0] != '#') { color[n] = (char *)malloc(sizeof(char)*(strlen(str)+1)); /* 动态分配 */ strcpy(color[n], str); /* 将输入的字符串赋值给动态内存单元 */ n++; } for(i = n-1; i >= 0; i--) printf("%s ", color[i]); return 0; 采用动态分配内存的方法处理多个字符串的输入的优点在于,能够根据实际输入数据的多少来申请和分配内存空间,从而提高了内存的使用率。 运行结果: red blue yellow # yellow blue red

11.1.4 用指针数组处理多个字符串 4.对指针数组的进一步讨论 11.1.4 用指针数组处理多个字符串 4.对指针数组的进一步讨论 char *color[ ] = {“red”, ”blue”, ”yellow”, ”green”, ”black”}; 数组名color代表数组首元素color[0]的地址,是指向指针的指针(二级指针) color+2指向color[2] ,*(color+2)和color[2]等价 color[0]指向字符串"red"的首字符r,color[0]+2指向首字符r后的第2个字符d

11.1.4 用指针数组处理多个字符串 4.对指针数组的进一步讨论 color[k]*(color+k) 11.1.4 用指针数组处理多个字符串 4.对指针数组的进一步讨论 color[k]*(color+k) printf("%s", color[2]); printf("%s", *(color+2)); *(color[k]+j)  *(*(color+k)+j)  color[k][j] printf("%c %c", *(color[2]), *(color[2]+2)); printf("%c %c", color[2][0], color[2][2]);

11.1.4 用指针数组处理多个字符串 例11-6 解密藏头诗。所谓藏头诗,就是将一首诗每一句的第一个字连起来,所组成的内容就是该诗的真正含义。编写程序,输出一首藏头诗的真实含义。 一叶轻舟向东流, 帆梢轻握杨柳手, 风纤碧波微起舞, 顺水任从雅客悠。

11.1.4 用指针数组处理多个字符串 #include <stdio.h> 11.1.4 用指针数组处理多个字符串 #include <stdio.h> char *change(char s[][20]); int main(void) { int i; char *poem[4] = { "一叶轻舟向东流,", "帆梢轻握杨柳手,", "风纤碧波微起舞,", "顺水任从雅客悠。"}; /* 指针数组初始化 */ char mean[10]; for(i = 0; i<4; i++){ /* 每行取第1个汉字存入mean */ mean[2 * i] = *(poem[i]); mean[2 * i + 1] = *(poem[i] + 1); } mean[2 * i] = ’\0’; printf("%s\n", mean); /* 输出结果 */ return 0;

*11.1.5 命令行参数 C语言源程序经编译和连接处理,生成可执行程序(例如test.exe)后,才能运行。 *11.1.5 命令行参数 C语言源程序经编译和连接处理,生成可执行程序(例如test.exe)后,才能运行。 在DOS环境的命令窗口中,输入可执行文件名,就以命令方式运行该程序。 输入命令时,在可执行文件(命令)名的后面可以跟一些参数,这些参数被称为命令行参数 test world (test是命令名,world是命令行参数)

*11.1.5 命令行参数 命令行的一般形式为: 命令名 参数1 参数2 … 参数n *11.1.5 命令行参数 命令行的一般形式为: 命令名 参数1 参数2 … 参数n 使用命令行的程序不能在编译器中执行,需要将源程序经编译、链接为相应的命令文件(一般以.exe为后缀),然后回到命令行状态,再在该状态下直接输入命令文件名。 命令名和各个参数之间用空格分隔,也可以没有参数

*11.1.5 命令行参数 带参数的main()函数格式: int main(int argc, char *argv[ ]) *11.1.5 命令行参数 带参数的main()函数格式: int main(int argc, char *argv[ ]) { ...... } 第1个参数argc接收命令行参数(包括命令名)的个数;第2个参数argv接收以字符串常量形式存放的命令行参数(包括命令名本身也作为一个参数)。

*11.1.5 命令行参数 【例11-7】编写C程序echo,它的功能是将所有命令行参数在同一行上输出。 *11.1.5 命令行参数 【例11-7】编写C程序echo,它的功能是将所有命令行参数在同一行上输出。 #include <stdio.h> int main(int argc, char *argv[ ]) { int k; for(k = 1; k < argc; k++) /* 从第1个命令行参数开始 */ printf("%s ", argv[k]); /* 打印命令行参数 */ printf("\n"); return 0; } 运行结果 在命令行状态下输入: echo How are you? 输出: How are you?

11.2 字符定位 11.2.1 程序解析 11.2.2 指针作为函数的返回值 *11.2.3 指向函数的指针

11.2.1 程序解析 例11-8 输入一个字符串和一个字符,如果该字符在字符串中,就从该字符首次出现的位置开始输出字符串中的字符。例如,输入字符r和字符串program后,输出rogram。 要求定义函数match(s, ch),在字符串s中查找字符ch,如果找到,返回第一次找到的该字符在字符串中的位置(地址);否则,返回空指针NULL。

11.2.1 程序解析 运行结果1 Please Input the string: University v versity 运行结果2 school a Not Found 11.2.1 程序解析 #include <stdio.h> char *match(char *s, char ch) /* 函数返回值的类型是字符指针 */ { while(*s != '\0') if(*s == ch) return(s); /* 若找到字符ch,返回相应的地址 */ else s++; return(NULL); /* 没有找到ch,返回空指针 */ } int main(void ) { char ch, str[80], *p = NULL; printf(“Please Input the string:\n”); /* 提示输入字符串 */ scanf("%s", str); getchar(); /* 跳过输入字符串和输入字符之间的分隔符 */ ch = getchar(); /* 输入一个字符 */ if((p = match(str, ch)) != NULL) /* 调用函数match() */ printf("%s\n", p); else printf("Not Found\n"); return 0; 函数match()返回一个地址(指针)。 在主函数中,用字符指针p接收match()返回的地址,从p指向的存储单元开始,连续输出其中的内容,直至'\0'为止。

11.2.2 指针作为函数的返回值 函数返回值的类型 在C语言中,函数返回值也可以是指针,定义和调用这类函数的方法与其他函数是一样的。 整型 11.2.2 指针作为函数的返回值 函数返回值的类型 整型 浮点型 字符型 结构类型 指针(返回一个地址) 在C语言中,函数返回值也可以是指针,定义和调用这类函数的方法与其他函数是一样的。

11.2.2 指针作为函数的返回值 思考:在例11-8中,如果将str的定义及相应的数据输入都放在函数match() 中,结果会如何? 11.2.2 指针作为函数的返回值 思考:在例11-8中,如果将str的定义及相应的数据输入都放在函数match() 中,结果会如何? char * match() { char ch, str[80],*s=str; /* 定义局部字符数组 */ printf("Please Input the string:\n"); /* 输入 */ scanf("%s", str); getchar(); ch = getchar(); while(*s != '\0') if(*s == ch) return s; /* 返回局部字符数组地址 */ else s++; return(NULL); } 不能返回在函数内部定义的局部数据对象的地址,这是因为所有的局部数据对象在函数返回时就会消亡,其值不再有效 返回指针的函数一般都返回全局数据对象或主调函数中数据对象的地址

*11.2.3 指向函数的指针 每个函数都占用一段内存单元,它们有一个入口地址(起始地址) 在C语言中,函数名代表函数的入口地址。 *11.2.3 指向函数的指针 每个函数都占用一段内存单元,它们有一个入口地址(起始地址) 在C语言中,函数名代表函数的入口地址。 我们可以定义一个指针变量,接收函数的入口地址,让它指向函数,这就是指向函数的指针,也称为函数指针。 通过函数指针可以调用函数,它也可以作为函数的参数。 指令1 指令2 指令3 … 指令n 入口地址

*11.2.3 指向函数的指针 1.函数指针的定义 函数指针定义的一般格式为: 类型名 (*变量名)( 参数类型表); 例如: *11.2.3 指向函数的指针 1.函数指针的定义 函数指针定义的一般格式为: 类型名 (*变量名)( 参数类型表); 类型名指定函数返回值的类型,变量名是指向函数的指针变量的名称。 例如: int (*funptr)( int, int); 定义一个函数指针funptr,它可以指向有两个整型参数且返回值类型为int的函数。

*11.2.3 指向函数的指针 2.通过函数指针调用函数 通过函数指针调用函数的一般格式为: (*函数指针名)(参数表) 例如: *11.2.3 指向函数的指针 2.通过函数指针调用函数 通过函数指针调用函数的一般格式为: (*函数指针名)(参数表) 例如: int fun(int x, int y); int (*funptr)(int, int); funptr = fun; (*funptr)(3 , 5);

*11.2.3 指向函数的指针 3.函数指针作为函数的参数 C语言的函数调用中,函数名或已赋值的函数指针也能作为实参,此时,形参就是函数指针,它指向实参所代表函数的入口地址。 例如: f(int (*funptr)(int, int)) {…} void main() { … int (*funptr)(int, int); funptr = fun; f( funptr ); … }

*11.2.3 指向函数的指针 【例11-9】编写一个函数calc(f, a, b),用梯形公式求函数f(x)在[a, b]上的数值积分。 *11.2.3 指向函数的指针 【例11-9】编写一个函数calc(f, a, b),用梯形公式求函数f(x)在[a, b]上的数值积分。 然后调用该函数计算下列数值积分。(函数指针作为函数参数示例) 分析:calc()是一个通用函数,用梯形公式求解数值积分。它和被积函数f(x)以及积分区间[a, b]有关,相应的形参包括函数指针、积分区间上下限参数。在函数调用时,把被积函数的名称(或函数指针)和积分区间的上下限作为实参。

*11.2.3 指向函数的指针 运行结果 1: resule=0.5000 2: resule=0.6481 *11.2.3 指向函数的指针 /* 计算数值积分(函数指针作为函数参数示例) */ int main(void) { double result; double (*funp)(double); result = calc(f1, 0.0, 1.0); /* 函数名f1作为函数calc的实参 */ printf("1: resule=%.4f\n", result); funp = f2; /* 对函数指针funp赋值 */ result = calc(funp, 1.0, 2.0); /* 函数指针funp作为函数calc的实参 */ printf("2: resule=%.4f\n", result); return 0; } /* 函数指针funp作为函数的形参 */ double calc(double (*funp)(double), double a, double b) { double z; z = (b-a)/2 * ((*funp)(a) + (*funp)(b)); /* 调用funp指向的函数 */ return(z); 运行结果 1: resule=0.5000 2: resule=0.6481

11.3 用链表构建学生信息库 11.3.1 程序解析 11.3.2 链表的概念 11.3.3 单向链表的常用操作

11.3.1 程序解析 例11-10 建立一个学生成绩信息(包括学号、姓名、成绩)的单向链表,学生记录按学号由小到大顺序排列,要求实现对成绩信息的插入、修改、删除和遍历操作。 main Create_Stu_Doc InsertDoc DeleteDoc Print_Stu_Doc

11.3.1 程序解析 struct stud_node{ /*链表结点类型*/ int num; char name[20]; 11.3.1 程序解析 struct stud_node{ /*链表结点类型*/ int num; char name[20]; int score; struct stud_node *next; }; struct stud_node * Create_Stu_Doc(); /* 新建链表 */ struct stud_node * InsertDoc(struct stud_node * head, struct stud_node *stud); /* 插入 */ struct stud_node * DeleteDoc(struct stud_node * head, int num); /* 删除 */ void Print_Stu_Doc(struct stud_node * head); /* 遍历 */

11.3.2 链表的概念 链表是一种常见而重要的动态存储分布的数据结构。它由若干个同一结构类型的“结点”依次串接而成。链表分单向链表和双向链表。 头指针 结点 尾结点 头结点

11.3.2 链表的概念 通常使用结构来定义单向链表结点的数据类型: struct stud_node{ int num; 11.3.2 链表的概念 通常使用结构来定义单向链表结点的数据类型: struct stud_node{ int num; char name[20]; int score; struct stud_node *next; }; 结构的递归定义

11.3.2 链表的概念 与数组比较 在用数组存放数据时,一般需要事先定义好固定长度的数组,在数组元素个数不确定时,可能会发生浪费内存空间的情况。 链表是动态存储分布的数据结构。根据需要动态地开辟内存空间,可以比较自由方便地插入新元素(结点),故使用链表可以节省内存,操作效率高。

11.3.2 链表的概念 动态分配相关函数 void *malloc(unsigned size) void free(void *ptr) 11.3.2 链表的概念 动态分配相关函数 void *malloc(unsigned size) 功能:在内存的动态存贮区中分配一块长度为size的连续空间。 返回值:指针,存放被分配内存的起始地址。若未申请到空间,则返回 NULL( 0 )。 例如:(int *) malloc(sizeof(int)) (struct student *) malloc(sizeof(struct student)) void free(void *ptr) 功能:释放由malloc()申请的动态内存空间,ptr存放该空间的首地址。 返回值:无。 例如:free(p);

11.3.3 单向链表的常用操作 1. 链表的建立 2. 链表的遍历 3. 插入结点 4. 删除结点

11.3.3 单向链表的常用操作 1. 链表的建立

11.3.3 单向链表的常用操作 1. 链表的建立 头部插入法: p->next=head; head=p; 尾部插入 11.3.3 单向链表的常用操作 1. 链表的建立 head = tail = NULL; scanf("%d%s%d", &num,name, &score); while(num != 0){ p = (struct stud_node *) malloc(size); p->num = num; strcpy(p->name, name); p->score = score; p->next = NULL; if(head == NULL) head = p; else tail->next = p; tail = p; scanf("%d%s%d", &num, name, &score); } 头部插入法: p->next=head; head=p; 尾部插入

11.3.3 单向链表的常用操作 2. 链表的遍历 for(ptr = head; ptr!=NULL; ptr = ptr->next) printf("%d\t%s\t%d\n", ptr->num, ptr->name, ptr->score);

11.3.3 单向链表的常用操作 先连: s->next = ptr->next; 后断: ptr->next = s; 11.3.3 单向链表的常用操作 3. 插入结点 head ptr s 先连: s->next = ptr->next; 后断: ptr->next = s;

11.3.3 单向链表的常用操作 4. 删除结点 head ptr1 ptr2 head ptr1 ptr2 11.3.3 单向链表的常用操作 4. 删除结点 head ptr1 ptr2 head ptr1 ptr2 ptr2=ptr1->next; 先接:ptr1->next=ptr2->next; ptr1->next = ptr1->next->next; 后删:free(ptr2);

本章总结 指针数组 指针与函数 单向链表 能够熟练掌握指针数组的操作与应用 能够熟练处理与操作函数与指针的各种关系 能够掌握单向链表的基本操作 指针数组 指针数组概念与应用 指向指针的指针(二级指针) 命令行参数 指针与函数 指针作为函数的返回值 函数指针 单向链表 链表的概念 结点的结构定义与动态分配 链表的基本操作(建立、遍历、插入、删除)