第8章 指针 21世纪高等学校精品规划教材.

Slides:



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

第七章 指针 计算机公共教学部.
第六章 指针 指针的概念 指针变量 指针与数组 指针与函数 返回指针值的函数.
第7章 指针 存储地址的变量的类型就是指针类型 能直接对内存地址操作, 实现动态存储管理 容易产生副作用, 初学者常会出错
电子成绩单项目实现.
二级指针与二维数组.
C语言程序设计基础 第10章 指针进阶 刘新国.
10.1 二级指针 10.2 指针与二维数组 10.3 指针的动态存储分配 10.4 函数指针 10.5 main函数的参数
第8章 指针 ● 8.1 指针简介 ● 8.2 指针变量的操作 ● 8.3 数组与指针 ● 8.4 二维数组与指针 ●本章小结 ●本章练习.
C语言基础——指针的高级应用 Week 05.
第6章 指针 6.1 指针的概念 6.2 变量与指针 6.3 数组与指针 6.4 字符串与指针 6.5 函数与指针 6.6 返回指针值的函数
6.4 字符串与指针 1. 用字符数组存放一个字符串.
第六节 二维数组和指针 二维数组的地址 对于一维数组: (1)数组名array表示数组的首地址, 即array[0]的地址;
8.1 指针的概念 8.2 指针变量 8.3 指针变量的基础类型 8.4 指针的运算 8.5 指针与一维数组 8.6 指针应用实例
C++中的声音处理 在传统Turbo C环境中,如果想用C语言控制电脑发声,可以用Sound函数。在VC6.6环境中如果想控制电脑发声则采用Beep函数。原型为: Beep(频率,持续时间) , 单位毫秒 暂停程序执行使用Sleep函数 Sleep(持续时间), 单位毫秒 引用这两个函数时,必须包含头文件
第九章 字符串.
第九章 指针 目录 指针与指针变量的概念 变量的指针和指向变量的指针变量 数组的指针和指向数组的指针变量
第5章 函数与模块化设计 学习目的与要求: 掌握函数的定义及调用方法 理解并掌握参数的传递方法 理解函数的嵌套与递归调用
第6章 指针 学习目的与要求: 了解指针的概念和相关术语 熟练掌握指向变量、数组和字符串的指针变量的使用方法 了解指向函数的指针变量
指 针 为什么要使用指针 指针变量 指针与数组 返回指针值的函数 动态内存分配 通过指针引用字符串 指向函数的指针 小 结 习 题.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
第八章 指 针 8.1 指针的概念与定义 8.2 指针作函数参数 8.3 指针与数组 8.4 指针与函数 8.5 复杂指针.
第 十 章 指 针.
项目六 用指针优化学生成绩排名 项目要求 项目分析
C语言高级编程(第四部分) 字符串 北京大学 信息科学技术学院.
第7章 间接访问—指针 指针的概念 指针运算与数组 动态内存分配 字符串再讨论 指针作为函数参数和返回值 指针数组与多级指针
Chap 8 指针 8.1 寻找保险箱密码 8.2 狸猫换太子 8.3 冒泡排序 8.4 加密变换问题 8.5 任意个整数求和问题*
辅导课程六.
第8章 善于利用指针 8.1 指针是什么 8.2 指针变量 8.3 通过指针引用数组 8.4 通过指针引用字符串 8.5 指向函数的指针
Zhao4zhong1 (赵中) C语言指针与汇编语言地址.
Zhao4zhong1 (赵中) C语言指针与汇编语言地址.
二维数组的指针表示 与复杂的指针例子 专题研讨课之三.
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
C语言程序设计基础 第8章 指针 刘新国.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
第二章 Java语言基础.
第8章 指针.
第六章 指针 指针的概念 指针的运算 指向变量的指针 指向数组的指针 指向函数的指针 二级指针 主讲:李祥 时间:2015年10月.
欲穷千里,更上层楼 第十章 指 针 指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构; 能很方便地使用数组和字符串; 并能象汇编语言一样处理内存地址,从而编出精练而高效的程序。指针极大地丰富了C语言的功能。 学习指针是学习C语言中最重要的一环,
第五章 习题课 电子信息与计算机科学系 曾庆尚.
第七章 操作符重载 胡昊 南京大学计算机系软件所.
9.1 地址、指针和变量 9.2 指针运算 9.3 指针与数组 9.4 函数与指针 9.5 程序综合举例 9.6 上机实训.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
資料結構與C++程式設計進階 排序與搜尋 講師:林業峻 CSIE, NTU 6/ 14, 2010.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
C语言复习3----指针.
C语言大学实用教程 第7章 指针 西南财经大学经济信息工程学院 刘家芬
函式庫補充資料.
指针 几个概念:  指针也是一种数据类型,具有指针类型的变量,称为指针变量。
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
第6讲 指针与引用 6.1 指针 6.2 引用.
C语言程序设计 第一章 数据类型, 运算符与表达式 第二章 顺序程序设计 第三章 选择结构程序设计 第四章 循环控制 第五章 数组.
第六章 指针 C++程序设计中使用指针可以: 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 动态分配内存 得到多于一个的函数返回值.
7.1 C程序的结构 7.2 作用域和作用域规则 7.3 存储属性和生存期 7.4 变量的初始化
第6章 指针 6.1 指针的概念 6.2 变量与指针 6.3 数组与指针 6.4 字符串与指针 6.5 函数与指针 6.6 返回指针值的函数
第十章 指针 指针是C语言的重要概念,是C语言的特色,是C语言的精华。 10.1 地址和指针的概念 内存中的每一个字节都有一个地址。
C qsort.
第九章 指针.
第九节 赋值运算符和赋值表达式.
3.16 枚举算法及其程序实现 ——数组的作用.
第8章 善于利用指针 8.1 指针是什么 8.2 指针变量 8.3 通过指针引用数组 8.4 通过指针引用字符串 8.5 指向函数的指针
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
本节内容 函数嵌套调用的内存布局 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
C程序设计.
C语言程序设计 第8章 指针.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
第七章 指针 指针与指针变量 指针与数组 指针与函数 指针与字符串.
第九章 指针 C程序设计中使用指针可以: 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 动态分配内存 得到多于一个的函数返回值.
第八章 指 针 北京邮电大学出版社.
Presentation transcript:

第8章 指针 21世纪高等学校精品规划教材

理解并掌握地址、指针和指针变量的概念 练掌握指针变量的定义、初始化和引用方法 理解并掌握指针与数组的关系 了解指针数组和多级指针的概念 了解指针与函数的关系 学会在程序设计中正确应用指针解决实际问题

引言 指针是C语言区别于其他程序设计语言的主要特征之一。

8.1 指针的概念 C语言允许使用变量名、数组名[下标]、函数名等标识符来访问内存 8.1 指针的概念 C语言允许使用变量名、数组名[下标]、函数名等标识符来访问内存 指针其实就是在内存中的地址,它可能是变量的地址,也可能是函数的入口地址 变量指针存储的地址是变量的地址 函数指针存储的地址是函数的入口地址 指针变量也简称为指针,是指它是一个变量,且该变量是指针类型的

8.2 指针变量的定义和初始化 定义指针变量的形式如下: 定义并初始化的形式为: 例如: 或者: 8.2 指针变量的定义和初始化 定义指针变量的形式如下: 数据类型 *指针变量名; 定义并初始化的形式为: 数据类型 *指针变量名=&变量名; 例如: int a; int *p=&a; 或者: int a,*p=&a; 没有指向的指针变量的值是随机的,称为“野指针”。

指针变量与 变量的关系 int a,*pa=&a;

8.3 指针运算 8.3.1 * 运算符和取地址运算符& int a=1000, *pa=&a; *(&a) == a &(*p) == p 8.3 指针运算 8.3.1 * 运算符和取地址运算符& int a=1000, *pa=&a; *(&a) == a &(*p) == p 指向运算符 * 和取地址运算符 & 互逆 不能写成: *(& p)

8.3.2 指针变量的引用 【例8-1】演示指针变量的引用 8.3.2 指针变量的引用 【例8-1】演示指针变量的引用 void swap1(int x , int y){int temp;temp = x;x = y;y = temp;} void swap2(int *x , int *y){int temp;temp = *x;*x = *y;*y = temp;} void swap3(int *x , int *y){int *temp;temp = x;x = y;y = temp;} void main() {int a,b; int *pa,*pb; pa=&a; pb=&b; a=10,b=20;swap1(a,b); printf("a=%d,b=%d,*pa=%d,*pb=%d\n",a,b,*pa,*pb); a=10,b=20;swap2(pa,pb); a=10,b=20;swap3(pa,pb); }

【例8-1】演示指针变量的引用。 swap1(int x,int y),主函数调用方式为: swap1(a,b); 值传递,a、b的值以及pa、pb指针变量都不受影响。 swap2(int *x,int *y),主函数调用方式为: swap2(pa,pb); 形参是指针变量,实参也是指针变量。交换算法中采用指向运算符*,所以*x、*y和pa、pb是对应相同的数据a、b,最后函数实现了交换。 swap3(int *x,int *y),主函数调用方式为: swap3(pa,pb); 形参是指针变量,实参也是指针变量。交换算法中临时指针变量虽然把x、y交换,但pa、pb没有交换,所以对应的数据a、b也没有受到影响,交换是失败的。

【例8-1】演示指针变量的引用。 swap3()分析图

8.3.3 指针的算术运算和关系运算 算术运算 指针变量的++和--运算。 指针加、减整数运算。 指向同一数组不同元素的指针相减运算。 8.3.3 指针的算术运算和关系运算 算术运算 指针变量的++和--运算。 指针加、减整数运算。 指向同一数组不同元素的指针相减运算。 假定有: char str[100]= "Hello World"; char *p=str,*q;

8.3.3 指针的算术运算和关系运算 p++ q=p+3; 字符W可以用str[6]表示,也可以用p[5]、q[2]表示

8.3.3 指针的算术运算和关系运算 指针不能进行如下等运算: 关系运算 关系运算是比较指针大小的运算。两个指针相等说明指向同一存储单元。 8.3.3 指针的算术运算和关系运算 关系运算 关系运算是比较指针大小的运算。两个指针相等说明指向同一存储单元。 p<q 指针不能进行如下等运算: p+q p*q p/q ……

8.4 指针与数组 8.4.1 指针与字符数组 char str[100]= "Hello World"; char *p=str; 8.4 指针与数组 8.4.1 指针与字符数组 char str[100]= "Hello World"; char *p=str; 字符w可以有如下多种表示形式: str[6] *(str+6) p[6] *(p+6)

【例8-2】演示指针和数组的关系。 #include <stdio.h> void main() { char str[100]="123456789"; char *p=str;char des[100],*q; while(*p != NULL) printf("%c",*p++); /*顺序输出*/ printf("\n"); while(--p >= str) printf("%c",*p); /*逆序输出*/ p=str; q=des; while(*p != NULL) *q++ = *p++; /*字符串拷贝*/ *q=NULL; printf("%s\n",des); return 0; }

8.4.2 指针与其他类型数组 【例8-3】演示指针和整型数组的关系,数组动态分配内存。 #include <stdio.h> 8.4.2 指针与其他类型数组 【例8-3】演示指针和整型数组的关系,数组动态分配内存。 #include <stdio.h> void main() { int a[10] = {1,2,3,4,5,6,7,8,9,10}; int *p=a,*q=p+9; int s; for(s = 0 ; q >= p ; q--) s = s + *q; printf("s=%d\n",s); }

8.4.3 指针与二维数组 二维数组其实可以看成由一维数组构造而成。就相当于几个队列构成一个方阵,方阵由队列组成,队列由具体的元素--人组成。 一级指针只能管理队列,如果管理方阵,则需要二级指针。 int a=1000,*pa,**ppa; pa=&a; ppa=&pa; *(*(ppa)) ≡ *(pa) ≡ a ≡ 1000

8.4.3 指针与二维数组 二级指针演示图

【例8-4】演示指针和二维数组的关系 main() { int s,t; int a[3][4]; int *p[3],*q; int i,j; s=t=0; for(i =0 ; i < 3 ; i++) { p[i] = a[i]; for(j = 0 ; j < 4 ; j++) a[i][j] = i * 3 + j; } for(i=0 ; i<3 ; i++) { q = p[i]; for(j=0 ; j<4 ; j++) {s = s + *(*(p+i)+j) ; t = t + *(q+j);} printf("s=%d,t=%d\n",s,t);

【分析】 int *p[3]是指针数组。 所谓指针数组,首先是一个数组,只不过其元素不是普通的变量,而是指针变量。即p[0]、p[1]、p[2]相当于前面提到的指针变量。 单独的指针变量可以指向一个一维数组,例如例题中的数组a的第一行

【分析】 p是指针数组的数组名 a[1][2]用p表示就是 *(*(p+1)+2),其实就是*(p[1]+2)、*(a[1]+2)

【总结】 p是二级指针 *p相当于*(p+0),级别降低为一级指针,相当于p[0]

8.5 指针与函数 8.5.1 指针作为函数的参数 实际调用该函数时,如: int swap2(int *x, int * y) 8.5 指针与函数 8.5.1 指针作为函数的参数 int swap2(int *x, int * y) { int temp; temp = *x; *x = *y; *y = temp; return 0; } 实际调用该函数时,如: swap2(&a,&b); 调用时,把实参的指针传送给形参,即传送&a、&b,这是函数参数的引用传递。但是,作为指针本身,仍然是函数参数的值传递方式。因为在swap函数中创建的临时指针在函数返回时被释放,它不能影响调用函数中的实参指针(即地址)值

8.5 指针与函数 8.5.2 函数指针 函数名代表了函数在内存中的入口地址 8.5 指针与函数 8.5.2 函数指针 函数名代表了函数在内存中的入口地址 int (*Copy)(const char *, const char*); Copy = &strcpy; /* Copy 指向strcpy函数 */ &运算符可以省略: Copy = strcpy; / *Copy 指向strcpy函数 */ 下面的3个调用是等价的: strcpy (des,str); /* 直接调用*/ (*Copy) ( des,str); /* 间接调用*/ Copy (des,str); /* 间接调用*/

【例8-5】演示函数指针。 #include <stdio.h> #include <math.h> int sum(int n) { int i,s=0; for(i=1; i<=n; i++) s = s + i; return s; } main() { double (*s)(double) = &sin; double PI=3.1415926; int (*f)(int); int n=100; printf("sin(PI/2)=%f\n",s(PI/2)); f=sum; printf("1+2+3+...+100=%d\n",f(n)); } 。

【例8-6】演示函数指针2。 #include <stdio.h> #include <math.h> int f1(int a,int b) { return a+b;} int f2(int a,int b) { return a-b;} int f3(int a,int b) { return a*b;} int f4(int a,int b) { if(b!=0) return a/b; else {printf("error\n");return 0; } }

【例8-6】演示函数指针2。 int f5(int a,int b) { if(b!=0) return a%b; else {printf("error\n");return 0;} } int f6(int n) { int i,s=0; for(i=1 ; i<=n ; i++)s = s + i; return s; int f7(int n) { int i,s=1; for(i=1 ; i<=n ; i++)s = s * i;

【例8-6】演示函数指针2。 int f8(int a,int b,int c) { return a+b+c;} void main() int (*f)(); int a,b,c; a=53; b=44; c=35; f=f1; printf("a+b=%d\n",f(a,b)); f=f2; printf("a-b=%d\n",f(a,b)); f=f3; printf("a*b=%d\n",f(a,b)); f=f4; printf("a/b=%d\n",f(a,b)); f=f5; printf("a%%b=%d\n",f(a,b)); f=f6; printf("1+2+3+...+100=%d\n",f(100)); f=f7; printf("1*2*3*...*8=%d\n",f(8)); f=f8; printf("a+b+c=%d\n",f(a,b,c)); }

8.5.3 返回指针的函数 函数的返回值可以是一个指针。需要返回指针的函数,其类型必须也是指针类型。例如: 8.5.3 返回指针的函数 函数的返回值可以是一个指针。需要返回指针的函数,其类型必须也是指针类型。例如: char * copy(char * s,char * t) { … return s; } 函数名copy和其返回值s的类型都是 char *。 注意copy是函数名,是一个指针常量,如果定义成: char (*copy)(…);加上括号的copy 是指针变量。 定义成指针变量的形式没有函数体部分,变量是简单的实体,不能再包括其他代码。

【例8-7】设计一个类似于strcpy的函数 #include <stdio.h> char* copy(char* s,char* t) { char *p=s,*q=t; while(*p != '\0') p++; while(*q != '\0') p++ = q++; *p ='\0'; return s; } main() { char s[100]="Hello "; char t[]="World!"; printf("%s\n",copy(s,t));

8.6 程序示例 【例8-8】编写一个查找字符位置的函数。 int atc(char *string,char c) 8.6 程序示例 【例8-8】编写一个查找字符位置的函数。 int atc(char *string,char c) { int pos=0; while(*string != c && *string != NULL) { pos++; string++;} if(*string == NULL) return 0; else return pos+1; } void main() { char str[]="Hello World!"; int pos; pos = atc(str,'o'); if(pos != 0) printf("o's position is:%d\n",pos); else printf("not found the char o\n"); pos = atc(str,'k'); pos!=0 ? printf("k's position is:%d\n",pos) : printf("not found the char k\n"); }

【例8-9】用指针方法统计字符串"I love music more than games "中单词的个数。 规定单词由字母组成,单词之间由空格分隔,字符串开始和结尾没有空格。 #include <stdio.h> void main() { char string[]="I love music more than games"; char *p=string; int n=0; while(*p != NULL) { if(*p == ' ') {n++; ++p;while(*p++ ==' '); } else p++; } n=n+1; printf("n=%d\n",n);

【例8-10】编写一个函数用来查找一个字符串在另外一个字符串中的位置,注意有可能出现多次,要求能够查找指定次数出现的位置。 #include <stdio.h> int at(char *,char *); int atn(char *,char *,int); void main() { int pos; char source[101],subs[21]; printf("Input a string:"); gets(source); printf("Input a substring:"); gets(subs); pos = at(subs,source); if(pos) printf("Found,The first posistion is :%d\n" ,pos + 1); else printf("Not found\n"); pos = atn(subs,source,2); if(pos) printf("Found,The second position is :%d\n" ,pos + 1); }

【例8-10】编写一个函数用来查找一个字符串在另外一个字符串中的位置,注意有可能出现多次,要求能够查找指定次数出现的位置。 int at(char *subs,char *source) { char *p1,*p2; p1 = source; p2 = subs; while(*p1 != '\0' && *p2 != '\0') { if(*p1 == *p2) { p2++; if(*p2 == '\0') return (int)(p1-source-(p2-subs)+1); } else p2=subs; p1++; return 0;

【例8-10】编写一个函数用来查找一个字符串在另外一个字符串中的位置,注意有可能出现多次,要求能够查找指定次数出现的位置。 int atn(char *subs,char *source,int times) { char *p1,*p2; p1 = source; p2 = subs; while(*p1 != '\0' && *p2 != '\0') { if(*p1 == *p2) { p2++; if(*p2 == '\0') { if(times == 1) return (int)(p1-source - (p2-subs)+1); else { p2=subs; times --;} } else p2=subs; p1++; return 0;

【分析】 程序中定位函数at用于查找第1次出现的位置,atn函数用于查到第n次出现的位置,指定第几次查找的函数在查找到目标串后需要考虑次数问题。atn函数可以替代at函数,替代的形式为: atn(subs,source,1); 查找算法的关键在于如何认定查找到的状态,确认找到了目标串时,正好是指针p2指向目标串的结束符,这一点非常重要,在这个状态下,指针p1指向找到位置的串的最后一个字符,所以在计算串的位置时需要减去串的长度,考虑到计数是从1开始,所以返回的位置表达式为: (int)(p1-source - (p2-subs)+1)

【例8-11】编写一个函数用来清理一个字符串中的空格,将多个连续的空格合并为一个空格 例如下面的字符串: I like this games. 清理后变成: I like this games. 程序如下: #include <stdio.h> #include <string.h> char *DeleteOtherSpace(char *); void main() { char s[100]; printf("Input a string:"); gets(s); printf("%s\n",DeleteOtherSpace(s)); }

【例8-11】编写一个函数用来清理一个字符串中的空格,将多个连续的空格合并为一个空格 char *DeleteOtherSpace(char *s) { char *p,*q; int IfFirstSpace = 1; p=q=s; while(*p != '\0') { if(*p != '□') {*q++ = *p++;IfFirstSpace = 1; /*遇到非空格字符*/ } else if( IfFirstSpace ) /*遇到第1个空格字符*/ {*q++=*p++; IfFirstSpace = 0} else p++; /*遇到第2个以上的空格字符*/ *q = '\0'; return s;

本章介绍了指针的概念以及指针变量的定义和初始化等。C语言的指针变量形式有: 一级指针变量:int *p,p可指向变量、数组元素。 二级指针变量:int **pp,pp可指向一级指针变量。 指向一维数组的指针变量:int (*p)[n],可用于二维数组的行指针变量。 指针数组:int *p[n],元素是一级指针变量。 指向函数的指针变量:int (*p)(),p可指向一个函数。 返回指针的函数:int *f(){…},f函数返回一个一级指针。

指针的运算包括变量的取地址运算“&”和指针的指向运算“. ”。“&”和“ 指针的运算包括变量的取地址运算“&”和指针的指向运算“*”。“&”和“*”是一对互逆的运算符。除此以外,指针变量还可以进行受限制的算术运算、赋值运算和关系运算。 指针可以指向常变量、数组、函数。特别是指针作为函数的参数时,函数的参数传递方式变成地址传递,相对于值传递和引用传递有质的不同。 指针具有很大的灵活性和风险性,同时也是C语言功能强大的基础条件之一,希望读者认真学习。

写一个函数,求一个字符串的长度 输入一个字符串,将其逆序输出。 输入一行字符,将其中的每个字符从小到大排列后输出。 从字符串中删除子字符串。从键盘输入一字符串,然后输入要删除的子字符串,最后输出删除子串后的新字符串。