第九章 指针 目录 指针与指针变量的概念 变量的指针和指向变量的指针变量 数组的指针和指向数组的指针变量

Slides:



Advertisements
Similar presentations
《C语言程序设计》复习
Advertisements

C语言程序设计教程 单位:德州学院计算机系.
第8章 指针 ● 8.1 指针简介 ● 8.2 指针变量的操作 ● 8.3 数组与指针 ● 8.4 二维数组与指针 ●本章小结 ●本章练习.
C语言基础——指针的高级应用 Week 05.
C语言程序设计 第十二章 位运算.
第5章 函数与模块化设计 学习目的与要求: 掌握函数的定义及调用方法 理解并掌握参数的传递方法 理解函数的嵌套与递归调用
复习与总结.
程序设计基础.
第六章 数 组 主讲教师 贾月乐 联系电话:
C语言程序设计 课程 第5章 数组 主讲:李祥 博士、副教授 单位:软件学院软件工程系.
高级语言程序设计 主讲人:陈玉华.
由C程序结构所知,一个完整的C语言程序是由一个且只能有一个main()函数(又称主函数)和若干个其他函数组合而成的。而前面各章仅学习main()函数的编程,本章将介绍其他函数的编程,包括其他函数的定义、调用、参数传递及变量的作用域等。
循环结构又称为重复结构:用来处理需要重复处理的问题,它是程序中一种很重要的结构。
選擇排序法 通訊一甲 B 楊穎穆.
目录 10.1 指针的基本概念 10.2 指向变量的指针变量 10.3 指向数组的指针变量 10.4 指向函数的指针变量和指针型函数
项目六 用指针优化学生成绩排名 项目要求 项目分析
If … else 選擇結構 P27.
Introduction to the C Programming Language
目录 第八章 数组 1 简单学生成绩管理系统的开发 2 一维数组 3 多维数组 4 字符数组 5 数组作函数参数.
第七章 函数 目录 有参的加法函数的开发 函数定义的一般形式 函数参数和函数的值 函数的调用
计算概论 第十八讲 C语言高级编程 结构与习题课 北京大学信息学院.
Introduction to the C Programming Language
Chap 8 指针 8.1 寻找保险箱密码 8.2 角色互换 8.3 冒泡排序 8.4 电码加密 8.5 任意个整数求和*
C语言程序设计 李祥.
第八章 函数.
第8章 善于利用指针 8.1 指针是什么 8.2 指针变量 8.3 通过指针引用数组 8.4 通过指针引用字符串 8.5 指向函数的指针
第五章 指针 5.1 指针的概念和定义 5.2 指针运算 5.3 指针和数组 5.4 字符串指针 5.5 指针数组 5.6 指向指针的指针
C语言 程序设计基础与试验 刘新国、2012年秋.
第13章 结构体的应用 13.1 了解由用户构造的数据类型 13.2 结构体类型说明及结构体变量 13.3 结构体数组
第八章 使用指针.
計數式重複敘述 for 迴圈 P
Introduction to the C Programming Language
第十章 指针.
数组 梁春燕 华电信息管理教研室.
第1章 概述 本章要点: C语言程序结构和特点 C语言程序的基本符号与关键字 C语言程序的编辑及运行 学习方法建议:
六、函数 教学目标: 函数的概念、定义、调用和返回 带自定义函数的程序设计 递推算法 递归思想及算法实现 函数的参数传递方式 C语言程序设计.
第十章 用户自定义数据类型 目录 学生信息管理系统的开发 结构体数据类型的概述 结构体变量的使用 结构体数组
C语言概述 第一章.
第1讲 C语言基础 要求: (1) C程序的组成 (2) C语言的标识符是如何定义的。 (3) C语言有哪些基本数据类型?各种基本数
C语言大学实用教程 第5章 函数与程序结构 西南财经大学经济信息工程学院 刘家芬
資料結構與C++程式設計進階 排序與搜尋 講師:林業峻 CSIE, NTU 6/ 14, 2010.
C语言复习3----指针.
第一章 程序设计和C语言 主讲人:高晓娟 计算机学院.
C语言大学实用教程 第6章 数组 西南财经大学经济信息工程学院 刘家芬
Main() { Dfas Asdfasf fasdfa } #include <stdio.h> void main( ) {
函数 概述 模块化程序设计 基本思想:将一个大的程序按功能分割成一些小模块, 特点: 开发方法: 自上向下,逐步分解,分而治之
第八章 指標 (Pointer).
C语言的特点 1. C程序由许多函数组成 2. C程序必须有且只有一个主函数main( ) 3. 函数用“{”和“}”表示起点和终点
第六章 指针 C++程序设计中使用指针可以: 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 动态分配内存 得到多于一个的函数返回值.
7.1 C程序的结构 7.2 作用域和作用域规则 7.3 存储属性和生存期 7.4 变量的初始化
第十四章 若干深入问题和C独有的特性 作业: 函数指针 函数作参数 函数副作用 运算 语句 位段 存储类别 编译预处理
第十章 指针 指针是C语言的重要概念,是C语言的特色,是C语言的精华。 10.1 地址和指针的概念 内存中的每一个字节都有一个地址。
C程序设计.
本节内容 字符与字符串 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
C语言程序设计 李祥 QQ:
C程序设计.
第九章 指针.
第二章 类型、对象、运算符和表达式.
C/C++基礎程式設計班 C++: 物件的使用、參考、重載函式 講師:林業峻 CSIE, NTU 3/28, 2015.
C程序设计.
本节内容 指针类型.
第七章  数 组.
Introduction to the C Programming Language
第九章 指针 C程序设计中使用指针可以: 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 动态分配内存 得到多于一个的函数返回值.
Chap 10 函数与程序结构 10.1 圆形体积计算器 10.2 汉诺塔问题 10.3 长度单位转换 10.4 大程序构成.
第三章 流程控制 程序的运行流程 选择结构语句 循环结构语句 主讲:李祥 时间:2015年10月.
第六章 复合数据类型 指针的声明与使用 数组的声明与使用 指针与数组的相互引用 字符串及相关库函数 new与delete
本节内容 指针类型 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
C语言基础学习 从外行到入门.
C++语言程序设计 C++语言程序设计 第二章 基本数据类型与表达式 第十一组 C++语言程序设计.
Presentation transcript:

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

第九章 指针 目录 1 2 3 4 指针与指针变量的概念 变量的指针和指向变量的指针变量 数组的指针和指向数组的指针变量 字符串的指针与指向字符串的指针变量

知识点要求: 技能要求: 教学要求 1 指针变量作为函数参数的应用 2 3 4 1 2 3 提针的基本概念、指针变量的定义和引用 指向一维数组的指针变量的应用 4 指向二维数组的指针变量的应用 技能要求: 1 掌握指针变量的定义及使用 2 理解指针变量作为函数参数的实质 3 理解行指针和列指针

9.1 指针与指针变量的概念 9.1.1 指针的引入示例 注意这三个变量的定义形式 【例9.1】 #include <stdio.h> void main() { int hour,minute,second; int *phour,*pminute,*psecond; printf(“请输入小时,分,秒:”); scanf(“%d%d%d”,&hour,&minute,&second); printf(“以普通方式输出的时间是:%d:%d:%d\n”, hour,minute,second); phour=&hour; pminute=&minute; psecond=&second; printf(“以指针方式输出的时间是:%d:%d:%d\n”, *phour,*pminute,*psecond); return;} 注意这三个变量的定义形式

9.1 指针与指针变量的概念 9.1.2 指针和指针变量的概念 内存中每个字节有一个编号,就是“地址” 。如在程序中定义了变量,在对程序进行编译时,系统就会给这个变量分配内存单元。 例如有以下程序段: short x,y,z; x=3; y=4; z=x+y; 在内存中的示意图如下页所示:

内存中分配1000H开始的2个字节给变量x,分配1002H开始的2个字节给变量y,分配1004H开始的2个字节给变量z 。 有语句pointer=&x; 内其中&为取地址运算符,通过该运算符获取变量x的指针,该语句将x的地址赋给特殊的变量pointer。

9.1 指针与指针变量的概念 指针:是具有某种数据类型的存储单元的地址 。 例如,地址1000H是上述变量x的指针。 指针变量:如果有一个变量专门用来存放另一变量的地址(即指针),则它称为指针变量。 如上述的pointer就是一个指针变量,此处存储了变量x的地址。

9.2 变量的指针和指针变量 9.2.1 变量的指针 变量的指针是指变量在内存中所分配的具有某种数据类型的存储单元的地址。 常量、普通表达式以及寄存器变量等没有指针的概念 ,而&3、&(x+5)等都是非法的。

9.2 变量的指针和指针变量 9.2.2 指向变量的指针变量 定义指针变量的形式: 类型标示符 *指针变量名; 合法的定义: 类型标示符 *指针变量名; 合法的定义: float *pointer_3; char *pointer_4;

9.2 变量的指针和指针变量 可用赋值语句使一个指针变量得到另一个变量的地址,使它指向该变量。 例如: int i, j, ; int *pointer_1, *pointer_2; pointer_1=&i; pointer_2=&j;

9.2 变量的指针和指针变量 几点说明: (1)变量名前面的符号“*”仅表示所定义的变量是指针变量,它不是变量名的构成部分。 例如: float *pointer_1; 指针变量名是什么?

9.2 变量的指针和指针变量 几点说明: (2)指针变量定义后,它并没有明确指向任何变量,只有在给所定义的指针变量赋值(赋指针)时,指针变量才明确指向某变量 。 注意此处的&不能少,表示取变量x的地址 如: int *pointer,x; x=3; pointer=&x; //使指针变量pointer指向变量x

此处指针变量p的指向类型和变量a的类型不一致 9.2 变量的指针和指针变量 几点说明: (3) 指针变量的类型一方面是用来说明该变量是指针变量,另一方面是用来说明该指针变量可以指向的变量的类型 。 例如: int a=10; float *p=&a; printf(“%f”,*p); 运行的结果是0.000000,而不是10.00000。 此处指针变量p的指向类型和变量a的类型不一致 指针变量与所指向的变量类型不一致,将得到错误的结果。

9.2 变量的指针和指针变量 9.2.3 指针变量的引用 注意:指针变量中只能存放地址(指针),不能将一个整数(或任何其他非地址类型的数据)赋给一个指针变量。 相关运算符: & :取地址运算符; * :指针运算符,取其指向的内容。 例如: &a为变量a的地址, *p表示指针变量p所指向的变量

【例9.2】:通过指针变量访问整型变量 输出结果: #include <stdio.h> void main ( ) { int a,b; int *pointer_1, *pointer_2; a=100;b=10; pointer_1=&a; pointer_2=&b; printf(”%d,%d \n”,a,b); printf(”%d ,%d \n”,*pointer_1, *pointer_2); } 输出结果:

9.2 变量的指针和指针变量 说明: 执行语句 pointer_1=&a; (1)&* pointer_1的含义是什么? 如果有pointer_2 =&* pointer_1 ;它的作用是将&a(a的地址)赋给pointer_2 ,如pointer_2原来指向b,经过重新赋值后它指向a。

9.2 变量的指针和指针变量 (2) *&a的含义是什么? 先进行&a运算,得a的地址,再进行*运算。 *&a和*pointer_1的作用一样,都等价于变量a。即*&a与a等价。 (3) (*pointer_1)++相当于a++。

9.2 变量的指针和指针变量 例9.3: 输入a和b两个整数,按先大后小的顺序输出。 #include <stdio.h> 例9.3: 输入a和b两个整数,按先大后小的顺序输出。 #include <stdio.h> void main() {int *p1, *p2, *p,a,b; scanf("%d,%d",&a,&b); p1=&a; p2=&b; if (a<b) {p=p1; p1=p2; p2=p; } printf("a=%d,b=%d\n",a,b); printf("max=%d,min=%d\n",*p1,*p2); return; } 思考:输入5,9,输出结果是什么?

9.2 变量的指针和指针变量 运行情况如下: 5,9↙ a=5,b=9 max=9,min=5 当输入a=5,b=9时,由于a<b,将p1和p2交换。交换前的情况见图(a),交换后见图(b)。

9.2 变量的指针和指针变量 思考:如何通过指针真正交换变量a和b的值?

9.2 变量的指针和指针变量 9.2.4 指针变量作为函数参数 函数的参数不仅可以是整型、实型、字符型等数据,还可以是指针类型。它的作用是将一个变量的地址传送到另一个函数中。 【例9.4】对输入的两个整数按大小顺序输 出。 要求:设计一个函数来实现两个整数交换 试分析下面程序能实现这一功能吗?

思考:输入5,9,输出的结果是? #include <stdio.h> void main( ) {void swap(int p1,int p2); int a,b; scanf("%d,%d",&a,&b); printf("before swapping a=%d,b=%d\n",a,b); if(a<b) swap( a,b); printf("after swapping a=%d,b=%d\n", a, b); } 思考:输入5,9,输出的结果是? void swap(int p1,int p2) {int temp; temp=p1; p1=p2;p2=temp;}

修改后的程序: 输出结果: 若将swap函数做如下修改,请思考输出结果? void swap(int *p1,int *p2) {int *temp; temp=p1; p1=p2; p2=temp;} 修改后的程序: void swap(int *p1,int *p2) {int temp; temp=*p1; *p1=*p2; *p2=temp;} #include <stdio.h> void main( ) {void swap(int *p1,int *p2); int a,b; scanf("%d,%d",&a,&b); printf("before swapping a=%d,b=%d\n",a,b); if(a<b) swap( &a,&b); printf("after swapping a=%d,b=%d\n", a, b); } 输出结果:

9.2 变量的指针和指针变量 练习: 编写一个函数实现分离某个三位数的个位、十位、百位,并在main函数中对该函数进行测度,main函数可以参考如下程序段。

9.2 变量的指针和指针变量 参考程序段: #include <stdio.h> void main( ) {int num,gw,sw,bw; scanf("%d",&num); while(1) { if (num>1000 || num<100) {printf("不是三位数,请重新输入"); scanf("%d",&num);} else break; } 此处调用函数 此处输出num的个位、十位和百位

9.3 数组的指针和指向数组的指针变量 一个数组包含若干元素,每个数组元素在内存中都占用存储单元,有相应的地址,数组元素的地址也可称为数组元素的指针。 指针变量既可指向变量,也可指向数组元素(把某一元素的地址放到一个指针变量中)。

9.3 数组的指针和指向数组的指针变量 9.3.1 一维数组的指针与指向一维数组的指针变量 定义一个数组 例如:int a[10]; C编译系统将为数组a的所有元素在内存中分配一片连续的空间,数组名a代表这片连续空间的起始地址,它也是第0个数组元素的指针。 注意:数组名是一个指针,但不是指针变量,所以不能对数组名赋值。

数组的每一个元素都有一个指针,数组名a就是数组第0个元素a[0]的指针&a[0] ,a+i就是数组第i个元素a[i]的指针&a[i],如下图所示: int型数组的每一个元素均相当于一个int型变量,因此int型的指针变量可以指向int型数组的任何一个元素 。 例如: int *p,*q; p=a; q=&a[4]; 执行上述三条语句后指针变量p和q的指向如上图所示。

9.3 数组的指针和指向数组的指针变量 在定义指针变量时,可直接赋值。如: int *p; p=&a[0]; 等价于: int *p=&a[0]; 或: int *p=a; 将数组a的首地址赋给指针变量p,并不是赋给*p,*只是指明p是一个指针变量。

9.3 数组的指针和指向数组的指针变量 通过指针引用数组元素 C规定:如果指针变量p已指向数组中的一个元素,则p+1指向数组中的下一个元素。 int a[10],*p=a; p++; 表示p现在指向a[1]元素; 问:p + i ? a + i ? 代表a[i]的地址,指向a数组中的第i个元素。 *(a+i)或*(p+i)代表什么? 代表数组元素a[i]。

9.3 数组的指针和指向数组的指针变量 引用数组元素: (1) 下标法,如a[i]或p[i]形式; 其中a是数组名,p是指向数组元素的指针变量,其初值p=a。

9.3 数组的指针和指向数组的指针变量 【例9.6】 将数组中所有元素的值对称交换 解题思路: 【例9.6】 将数组中所有元素的值对称交换 解题思路: 设两个指针变量分别指向某次要交换的两个元素,交换后使begin往后移,end往前移,通过循环实现所有对称元素的交换。 1 2 3 4 5 6 7 8 9 begin end

9.3 数组的指针和指向数组的指针变量 【例9.6】 将数组中所有元素的值对称交换 解题思路: 【例9.6】 将数组中所有元素的值对称交换 解题思路: 设两个指针变量分别指向某次要交换的两个元素,交换后使begin往后移,end往前移,通过循环实现所有对称元素的交换。 1 2 3 4 5 6 7 8 9 begin end

9.3 数组的指针和指向数组的指针变量 【例9.6】 将数组中所有元素的值对称交换 解题思路: 【例9.6】 将数组中所有元素的值对称交换 解题思路: 设两个指针变量分别指向某次要交换的两个元素,交换后使begin往后移,end往前移,通过循环实现所有对称元素的交换。 1 2 3 4 5 6 7 8 9 begin end

9.3 数组的指针和指向数组的指针变量 【例9.6】 将数组中所有元素的值对称交换 解题思路: 【例9.6】 将数组中所有元素的值对称交换 解题思路: 设两个指针变量分别指向某次要交换的两个元素,交换后使begin往后移,end往前移,通过循环实现所有对称元素的交换。 1 2 3 4 5 6 7 8 9 begin end

输出结果: #include <stdio.h> void main() { int t,a[10]={0,1,2,3,4,5,6,7,8,9}; int *begin,*end; begin=&a[0]; end=&a[9]; while (begin<end) { t=*begin; *begin=*end; *end=t; begin++; end--; } begin=a; while(begin<a+10) printf("%3d",*begin++); printf("\n"); return; 输出结果:

9.3 数组的指针和指向数组的指针变量 思考:采用多种方法 输出整型数组a中的全部元素。 (1)下标法: #include <stdio.h> void main() {int a[10], i; for (i=0;i<10;i++) scanf("%d",&a[i]); printf("\n"); printf("%d",a[i]); }

9.3 数组的指针和指向数组的指针变量 (2)通过数组名计算数组元素地址,找出元素的值: #include <stdio.h> void main() {int a[10], i; for (i=0;i<10;i++) scanf("%d",&a[i]); printf("\n"); printf("%d",*(a+i)); }

9.3 数组的指针和指向数组的指针变量 (3)用指针变量指向数组元素: #include <stdio.h> void main() {int a[10],i,*p; for (i=0;i<10;i++) scanf("%d",&a[i]); printf("\n"); for (p=a;p<a+10;p++) printf("%d ",*p); }

9.3 数组的指针和指向数组的指针变量 9.3.2 一维数组的指针作函数参数 可以用一维数组名、一维数组第0个元素的指针或指向数组的指针变量作为函数的实参。 注意:用一维数组的指针作函数参数时,一定要注意形参与实参的类型要一致。

9.3 数组的指针和指向数组的指针变量 形参数组或形参指针变量所表示的形参数组与实参数组共用一段内存,在函数调用时,形参数组也没有分配新的存储单元,而是以实参数组的起始地址作为形参数组的起始地址 ,也就是说,形参数组的第i个元素与实参数组的第i个元素占用同一个存储单元,在函数调用过程中形参数组元素的值如果发生了变化,也会使实参数组元素的值发生变化

9.3 数组的指针和指向数组的指针变量 【例9.7】 改写例题9.6,定义一个exchange函数实现数组对称位置元素交换。 void exchange(int b[]) { int t,*end=b+N-1; while (b<end) {t= *b; *b= *end;*end=t; b++;end--; } 请编写出主程序。

9.3 数组的指针和指向数组的指针变量 说明: 实参数组名代表该数组首元素的地址,而形参是用来接收从实参传递过来的地址,所以,形参是一个指针变量(只有指针变量才能存放地址)。 C编译都是将形参数组名作为指针变量来处理。 void f(int arr[],int n) 等价于: void f(int *arr,int n) 函数被调用时,系统会建立一个指针变量arr,用来存放从实参传过来的数组首地址。

9.3 数组的指针和指向数组的指针变量 数组作为参数时,实参与形参的对应关系有以下4种情况: (1) 形参和实参都用数组名,如: void main() void f(int x[], int n) { int a[10]; { … … f(a,10); } }

9.3 数组的指针和指向数组的指针变量 (2) 实参用数组名,形参用指针变量。如: void main( ) void f(int *x,int n) { int a[10]; { … … f(a,10); } }

9.3 数组的指针和指向数组的指针变量 (3)实参形参都用指针变量。例如: void main() void f(int *x,int n) { int a[10], *p=a; { ┇ ┇ f(p,10); } }

9.3 数组的指针和指向数组的指针变量 (4) 实参为指针变量,形参为数组名。如: void main() void f(int x[ ],int n) { int a[10] , *p=a ; { ┇ ┇ f(p,10); } }

9.3 数组的指针和指向数组的指针变量 练习: 写一函数,求一个字符串的长度。在main函数中输入字符串,并输出其长度。 分别在程序中按以下两种情况处理: (1)函数形参用数组名。 (2)函数形参用指针变量。

9.3 数组的指针和指向数组的指针变量 9.3.3 二维数组的指针与指向二维数组的指针变量 1. 指向二维数组元素的指针变量 有如下定义: int a[3][4]; C编译系统将为数组a的所有元素在内存中分配一片连续的空间,数组名a代表这片空间的起始地址,它也是数组元素a[0][0]的地址。

9.3 数组的指针和指向数组的指针变量 二维数组的每一个元素a[i][j]都有一个指针(地址),它就是&a[i][j]。因此指针变量可以指向二位数组的任何一个元素 。 例如: int a[3][4]; int *p,*q; p=&a[0][0]; q=&a[2][3]; 网络工程 12.10 6与行、列下标的规律?

9.3 数组的指针和指向数组的指针变量 说明: 如果指针变量p的初值为&a[0][0],二维数组的大小为m×n,则: (1)*(p+k)与a[k/n][k%n]等价 a[i][j]与*(p+i*n+j)等价。 (2)指向二维数组元素的指针变量也可以带下标使用,如p[k]与*(p+k)等价。

9.3 数组的指针和指向数组的指针变量 对数组元素的引用有两种方法: ① 下标法,如a[i][j]或p[k]形式; ② 指针法,如*(p+i*n+j)或*(p+k)形式。 ③ 指针变量p可以进行自增自减运算,如*p++或*(p++)代表先对指针变量p所指向的二维数组元素进行引用,然后使指针变量p指向二维数组的下一个元素。

【例9.8】使用指向二维数组元素的指针实现对二维数组元素的访问。 #include <stdio.h> void main( ) { int a[3][4]= {1,2,3,4,8,7,6,5,4,1,9,6}; int *p,i,j,k; p=&a[0][0]; printf("output 1:\n"); while (p<=&a[2][3]) { printf("%3d", *p++); if ((p-&a[0][0])%4= =0) printf("\n"); } 注意该if语句的作用

p=&a[0][0]; //注意指针变量p的指向 printf("output 2:\n"); for (k=0;k<3*4;k++) { printf("%3d",p[k]); if ((k+1)%4= =0) printf("\n"); } printf("output 3:\n"); for (i=0;i<3;i++) { for (j=0; j<4;j++) printf("%3d",*(p+i*4+j)); printf("\n"); return;

9.3 数组的指针和指向数组的指针变量 二维数组不仅可以看成是由所有二维数组元素组成的集合,而且也可以看成是由一维数组组成的二维数组。 2 .二维数组的行指针与指向一维数组的指针变量 二维数组不仅可以看成是由所有二维数组元素组成的集合,而且也可以看成是由一维数组组成的二维数组。

9.3 数组的指针和指向数组的指针变量 a a+1 a+2 例: int a[3][4]={{1,3,5,7}, {9,11,13,15},{17,19,21,23}}; a[0] a[0]+1 a[0]+2 a[0]+3 列指针 a a[0] a[1] a[2] 1 3 5 7 9 11 13 15 17 19 21 23 a+1 a+2 行指针

9.3 数组的指针和指向数组的指针变量 注意: (1)二维数组的起始地址a、二维数组第0行的起始地址&a[0]及元素a[0][0]的起始地址&a[0][0]的地址值相同,但是,数组名a只能理解为a[0]的指针,不能理解为a[0][0]的指针。

9.3 数组的指针和指向数组的指针变量 (2)a+i与&a[i]等价,它们都是二维数组第i行的行指针,代表第i行的起始地址;*(a+i) 与a[i]和&a[i][0]等价,它们都是二维数组第i行第0列元素的元素指针,代表元素a[i][0]的地址。

9.3 数组的指针和指向数组的指针变量 前面的例题中定义的指针变量p指向一个整型数组元素,p+1指向下一个元素。 还可定义行指针,使p不指向一个数组元素,而指向一个包含m个元素的一维数组;p先指向a[0], p+1指向a[1]。 定义形式:int (*p)[4] ; *表示p是指针变量, 且p所指向的对象是有4个整型元素的数组,p+1的值比p的值增加了4*4个字节(即一维数组的长度)。

9.3 数组的指针和指向数组的指针变量 如果指向包含n个元素的一维数组的指针变量p的初值为a,二维数组a的大小为m×n,则通过二维数组的行指针或指向一维数组的指针变量来引用二维数组元素的方法是: ①下标法,如a[i][j]或p[i][j]形式; ②指针法,如*(*(a+i)+j)或*(*(p+i)+j)形式。 ③下标指针混合法,如*(a[i]+j)、*(p[i]+j)、(*(a+i))[j]、(*(p+i))[j]、*(a[0]+i*n+j)或(*a)[i*n+j]等形式。

9.3 数组的指针和指向数组的指针变量 【例9.9】 指向二维数组行的行指针的应用。 #include <stdio.h> void main( ) { int a[3][4]={1,2,3,4,8,7,6,5,4,1,9,6}; int (*p)[4],i,j; p=a; printf("output 1:\n"); while (p<a+3) { for (j=0; j<4; j++) printf("%3d", * (*p+j)); p++; printf("\n"); } 此处p为指向行的指针变量

p=a; // 注意指针变量p的指向 printf("output 2:\n"); for (i=0; i<3; i++) { for (j=0; j<4; j++) printf("%3d", * (*(p+i)+j)); printf("\n"); } return; 输出结果:

9.3 数组的指针和指向数组的指针变量 9.3.4 二维数组指针作函数参数 一维数组名可以作为函数参数,多维数组名也可作函数参数。 9.3.4 二维数组指针作函数参数 一维数组名可以作为函数参数,多维数组名也可作函数参数。 用指针变量作形参,以接受实参数组名传递来的地址。 可以有两种方法: ①用指向变量的指针变量(列指针) ②用指向一维数组的指针变量(行指针)

9.3 数组的指针和指向数组的指针变量 【例9.10】 有一个班,3个学生,各学4门课,计算总平均分数以及输出第i个学生的成绩。 解题思路:这个题目是很简单的。本例用指针作函数参数来实现。用函数average求总平均成绩,用函数search找出并输出第i个学生的成绩。

#include <stdio. h> int main() { void average(float #include <stdio.h> int main() { void average(float *p,int n); void search(float (*p)[4],int n); float score[3][4]={{65,67,70,60}, {80,87,90,81},{90,99,100,98}}; average(*score,12); search(score,2); return 0; } score[0][0]的地址

p 65 67 70 60 80 87 90 81 99 100 98 p+1 void average(float *p,int n) { float *p_end; float sum=0,aver; p_end=p+n-1; for( ;p<=p_end; p++) sum=sum+(*p); aver=sum/n; printf("average=%5.2f\n",aver); } p_end

void search(float (. p)[4],int n) { int i; printf("The score of No void search(float (*p)[4],int n) { int i; printf("The score of No.%d are:\n",n); for(i=0;i<4;i++) printf("%5.2f ",*(*(p+n)+i)); printf("\n"); } p 65 67 70 60 80 87 90 81 99 100 98 p+2

9.4 指向字符串的指针变量 9.4.1 字符串的表示形式 1. 用字符数组处理字符串 C语言中只有字符串常量的概念,没有字符串变量的概念,字符串变量是通过字符数组来实现的。

9.4 指向字符串的指针变量 【例 9.11】 利用字符数组处理字符串应用。 输出结果: #include <stdio.h> void main( ) { char str1[40]= "East China Geological institute", str2[ ]= "Informations Engineering Department"; int i=0; printf("%s\n",str1); while (str2[i]!='\0') printf("%c", str2[i++]); printf("\n"); return; } 输出结果:

9.4 指向字符串的指针变量 2. 指向字符的指针变量处理字符串 可以不定义字符数组,而定义一个指向字符的指针变量,并将字符串的起始地址赋给指针变量,通过该指针变量亦可以实现字符串的操作。

【例 9.12】 利用指向字符的指针变量处理字符串。 #include <stdio.h> void main( ) { char *str1="East China Geological institute", *str2=" Informations Engineering Department"; int i=0; printf("%s\n",str1); while (*str2) printf("%c", *str2++)); printf("\n"); return; } 输出结果:

9.4 指向字符串的指针变量 用指向字符的指针变量处理字符串与用字符数组处理字符串的许多操作都类似,但也有许多不同之处。主要区别有: (1) 在用字符数组处理字符串时,可以认为是将整个字符串的内容赋给了字符数组;但在用指向字符的指针变量处理字符串时,就不能认为是将整个字符串的内容赋给了指向字符的指针变量,而只是将字符串常量的指针赋给了该指针变量。

9.4 指向字符串的指针变量 (2) 数组名是指针常量,不能重新被赋值;而指向字符串的指针变量是可以被重新赋值的,即可以使指针变量重新指向其他字符。 (3) 要想将字符串常量直接赋给字符数组,只能通过初始化的方式实现,否则就只能将字符串常量每个字符逐个赋给字符数组的每个元素。

9.4 指向字符串的指针变量 str1定义为数组,如: char str1[20]=" hello world " ; 就不能写成: 等价于: char *str1; str1=" hello world " ;

9.4 指向字符串的指针变量 【例9.13】找出如下程序的错误,并加以改正。 void main( ) { char *p,s[80]; do { gets (s); while (*p) printf("%c", *p++); printf("\n"); }while(strcmp(s,"end")); //如果输入的字符串是“end”则结束循环 return; } 从考虑指针p的变化入手

9.4 指向字符串的指针变量 9.4.1 字符串指针作函数参数 【例 9.14】 用函数调用实现字符串的复制。 9.4.1 字符串指针作函数参数 【例 9.14】 用函数调用实现字符串的复制。 解题思路:定义一个函数copy_string用来实现字符串复制的功能,在主函数中调用此函数,函数的形参和实参可以分别用字符数组名或字符指针变量。分别编程,以供分析比较。

9.4 指向字符串的指针变量 #include <stdio.h> int main() {void copy_string(char from[],char to[]); char a[]="I am a teacher."; char b[]="you are a student."; printf(“a=%s\nb=%s\n",a,b); printf("copy string a to string b:\n"); copy_string(a,b); return 0; }

9.4 指向字符串的指针变量 数组名作形参: void copy_string(char from[], char to[]) { int i=0; while(from[i]!='\0') { to[i]=from[i]; i++; } to[i]='\0';

9.4 指向字符串的指针变量 指针变量形参: void copy_string(char *from, char *to) { for( ;*from!='\0'; from++,to++) { *to=*from; } *to='\0'; } 函数体有多种简化写法

9.4 指向字符串的指针变量 练习: 编写函数int cat_string(char *dst,char *src) 它的功能是将src所指向的字符串连接到 dst 所指向的字符串的后面,返回从 src中连接到 dst 后面的字符的个数。主函数接收从键盘输入的两个字符串,调用  cat_string 函数将后面的字符串连接到前面的字符串后面,将新字符串输出。

重点: 难点: 本章小结 1 2 3 1 2 3 指针变量的定义及使用 指针变量作为函数参数的应用 指向数组的指针变量的应用 指针变量作为函数的参数的实质 2 指向二维数组元素指针和行指针 3 字符数组与指向字符的指针变量的区别

本章结束!