slide1 n.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
第十章 指 针 PowerPoint Presentation
Download Presentation
第十章 指 针

Loading in 2 Seconds...

play fullscreen
1 / 108

第十章 指 针 - PowerPoint PPT Presentation


  • 87 Views
  • Uploaded on

本章内容 : 1. 地址和指针的概念 2. 变量的指针和指向变量的指针变量 3. 数组的指针和指向数组的指针变量 4. 字符串的指针和指向字符串的指针变量 5. 函数的指针和指向函数的指针变量 6. 指针数组和指向指针的指针. 第十章 指 针. 概 述: 指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。 利用指针变量 可以表示各种数据结构; 能很方便地使用数组和字符串; 并能象汇编语言一样处理内存地址,从而编出精练而高效的程序。

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about '第十章 指 针' - zandra


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
slide1

本章内容:

1.地址和指针的概念

2.变量的指针和指向变量的指针变量

3.数组的指针和指向数组的指针变量

4.字符串的指针和指向字符串的指针变量

5.函数的指针和指向函数的指针变量

6.指针数组和指向指针的指针

第十章 指 针

slide2

概 述:

指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。

利用指针变量可以表示各种数据结构; 能很方便地使用数组和字符串; 并能象汇编语言一样处理内存地址,从而编出精练而高效的程序。

指针极大地丰富了C语言的功能。 学习指针是学习C语言中最重要的一环,能否正确理解和使用指针是我们是否掌握C语言的一个标志。同时,指针也是C语言中最为困难的一部分,在学习中除了要正确理解基本概念,还必须要多编程,上机调试。只要作到这些,指针也是不难掌握的。

slide3

10.1 地址和指针的概念

在计算机中,所有的数据都是存放在存储器中的。 一般把存储器中的一个字节称为一个内存单元, 不同的数据类型所占用的内存单元数不等,如整型量占2个单元,字符量占1个单元等, 在第二章中已有详细的介绍。

为了正确地访问这些内存单元, 必须为每个内存单元编上号。 根据一个内存单元的编号即可准确地找到该内存单元。内存单元的编号也叫做地址。 既然根据内存单元的编号或地址就可以找到所需的内存单元,所以通常也把这个地址称为指针。

1、地址:内存单元的编号,通常一个字节(1B)一个编号。

2、指针:内存单元的地址。

slide4

内存

0

…...

2000

2001

2002

2003

2005

…...

  • 变量与地址

内存中每个字节有一个编号-----地址

程序中: int i;

float k;

i

编译或函数调用时为其分配内存单元

k

变量是对程序中数据

存储空间的抽象

slide5

3、内存单元的指针和内存单元的内容是两个不同的概念

4、内存数据的访问方式:

(1)直接访问——按变量名存取变量

(2)间接访问——将变量的地址存放在另一个变量(指针变量),通过指针变量来访问。

地址

……..

在C语言中, 允许用一个变量来存放指针,这种变量称为指针变量。一个指针变量的值就是某个内存单元的地址或称为某内存单元的指针。

2000

30

变量i

2002

50

变量j

2004

60

变量k

指针变量 ip

2000

slide6

…...

整型变量i

2000

10

2001

2002

2003

变量i_pointer

2004

2000

指针变量

2005

2006

…...

  • 直接访问与间接访问
    • 直接访问:按变量地址存取变量值
    • 间接访问:通过存放变量地址的变量去访问变量

例i=3; -----直接访问

3

20

例 *i_pointer=20; -----间接访问

slide7

…...

整型变量i

2000

10

2001

2002

2003

变量i_pointer

2004

2005

变量地址(指针)

指针变量

2006

地址存入

指针变量

指向

…...

变量值

变量

  • 指针与指针变量
    • 指针:一个变量的地址
    • 指针变量:专门存放变量地址的变量叫~

指针

变量的内容

变量的地址

2000

指针变量

slide8

注意:严格地说,一个指针是一个地址, 是一个常量。而一个指针变量却可以被赋予不同的指针值,是变量。 但经常把指针变量简称为指针。

为了避免混淆,我们中约定:

“指针”是指地址, 是常量,

“指针变量”是指取值为地址的变量。

定义指针的目的是为了通过指针去访问内存单元。

slide9

10.2 变量的指针和指向变量的指针变量

  • 变量的指针——变量的地址
  • 例:&a 为变量a在内存单的存放地址,也称变量a的指针
  • 指针变量——存放地址的变量
  • 指向变量的指针变量——一个指针变量存放变量a的地址,则称
  • 该指针变量为指向变量a的指针变量。

pa

a

例: int a=10;

int *pa

pa=&a

&a

10

slide10

一、指针变量的定义:

其一般形式为:

类型说明符 *变量名;

其中,*表示这是一个指针变量,变量名即为定义的指针变量名,类型说明符表示本指针变量所指向的变量的数据类型。

例如: int *p1;

表示p1是一个指针变量,它的值是某个整型变量的地址。 或者说p1指向一个整型变量。至于p1究竟指向哪一个整型变量, 应由向p1赋予的地址来决定。

slide11

再如:

static int *p2; /*p2是指向静态整型变量的指针变量*/

float *p3; /*p3是指向浮点变量的指针变量*/

char *p4; /*p4是指向字符变量的指针变量*/

应该注意的是,一个指针变量只能指向同类型的变量,

如: p3 只能指向浮点变量,不能时而指向一个浮点变量, 时而又指向一个字符变量。

slide12

二、指针变量的赋值

指针变量同普通变量一样,使用之前不仅要定义说明,而且必须赋予具体的值。未经赋值的指针变量不能使用, 否则将造成系统混乱,甚至死机。指针变量的赋值只能赋予地址, 决不能赋予任何其它数据,否则将引起错误。

C语言中提供了地址运算符&来表示变量的地址。

其一般形式为:& 变量名;

例如:&a变示变量a的地址,&b表示变量b的地址。 变量本身必须预先说明。设有指向整型变量的指针变量p,如要把整型变量a 的地址赋予p可以有以下两种方式:

(1)指针变量初始化的方法:

int a; int *p=&a;

(2)赋值语句的方法: int a, *p;

p=&a;

slide13

例int *p=&i;

int i;

  • 指针变量的初始化

一般形式:[存储类型]数据类型 *指针名=初始地址值;

例 int i;

int *p=&i;

赋给指针变量,

不是赋给目标变量

变量必须已说明过

类型应一致

例 int i;

int *p=&i;

int *q=p;

用已初始化指针变量作初值

例main( )

{ int i;

static int *p=&i;

..............

} ()

不能用auto变量的地址

去初始化static型指针

slide14

…...

整型变量i

2000

10

2001

2002

2003

指针变量p

2004

2005

随机

2006

…...

指针变量必须先赋值,再使用

例 main( )

{ int i=10;

int *p;

*p=i;

printf(“%d”,*p);

}

危险!

例main( )

{ int i=10,k;

int *p;

p=&k;

*p=i;

printf(“%d”,*p);

}

slide15

三、指针变量的运算(引用)

指针变量可以进行某些运算,但其运算的种类是有限的。 它只能进行赋值运算和部分算术运算及关系运算。

1.指针运算符

(1)取地址运算符 &

取地址运算符&是单目运算符,其结合性为自右至左,其功能是取变量的地址。例:&a 即变量a的地址

(2)取内容运算符 *

取内容运算符*是单目运算符,其结合性为自右至左,用来表示指针变量所指的变量。在*运算符之后跟的变量必须是指针变量。

例:int a=10 , *pa=&a;

*pa a 即为变量a 的值。

slide16

*i_pointer

i_pointer

10

2000

&i_pointer

i

…...

整型变量i

2000

10

2001

2002

2003

变量i_pointer

2004

2000

指针变量

2005

2006

…...

  • &与*运算符
    • 含义

含义: 取变量的地址

单目运算符

优先级: 2

结合性:自右向左

含义:取指针所指向变量的内容

单目运算符

优先级: 2

结合性:自右向左

  • 两者关系:互为逆运算
  • 理解

i_pointer = &i = &(*i_pointer)

i= *i_pointer = *(&i)

i_pointer &i &(*i_pointer)

i *i_pointer *(&i)

i_pointer-----指针变量,它的内容是地址量

*i_pointer----指针的目标变量,它的内容是数据

&i_pointer---指针变量占用内存的地址

slide17

注意:指针运算符*和指针变量说明中的指针说明符* 不是一回事。

在指针变量说明中,“*”是类型说明符,表示其后的变量是指针类型。

而表达式中出现的“*”则是一个运算符用以表示指针变量所指的变量。

main()

{ int a=5,*p=&a;

printf ("%d",*p);

}

表示指针变量p取得了整型变量a的地址。 本语句表示输出变量a 的值。

等价于: printf("%d",a);

slide18

说明:

若有定义: int a, *p=&a

(1) &*p 表示:p

(2) *&a 表示:a

(3) (*p)++ 相当于 a++

(4) *p++ 相当于 *(p++),即先取p所指向变量的值,然后,让p指向下一个存储单元。

(5) *++p 相当于 *(++p) 即先让p指向下一个存储单元,然后再取p所指向变量的值。

例: int a,b,*pa=&a,*pb=&b;

pa=pb;

*pa=*pb;

上面两个语句的含意是什么?

slide19

例y7-1.c:利用指针输入变量的值

main()

{ int a,b;

int *p;

p=&a;

scanf("%d",p);

p=&b;

scanf("%d",p);

printf(”a=%d, b=%d\n", a,b);

}

11

12

slide20

2 赋值运算

指针变量的赋值运算有以下几种形式:

①指针变量初始化赋值,前面已作介绍。

②把一个变量的地址赋予指向相同数据类型的指针变量。

例如: int a,*pa;

pa=&a; /*把整型变量a的地址赋予整型指针变量pa*/

③把一个指针变量的值赋予指向相同类型变量的另一个指针变量。

如: int a,*pa=&a,*pb;

pb=pa;

把a的地址赋予指针变量pb,

由于pa,pb均为指向整型变量的指针变量,

因此可以相互赋值

pa

a

&a

10

pb

&a

slide21

④把数组的首地址赋予指向数组的指针变量。

例如: int a[5],*pa;

pa=a; (C语言规定数组名表示数组的首地址)

也可写为: pa=&a[0];

数组第一个元素的地址也是整个数组的首地址,也可赋予pa

当然也可采取初始化赋值的方法:

int a[5],*pa=a;

⑤把字符串的首地址赋予指向字符类型的指针变量。

例如: char *pc;

pc="C language";

或用初始化赋值的方法写为:

char *pc="C Language";

这里应说明的是并不是把整个字符串装入指针变量, 而是把存放该字符串的字符数组的首地址装入指针变量。

slide22

说明:指针变量可以赋予0值,则p=0表明p是空指针,它不指向任何变量;在头文件"stdio.h"中有: #define NULL 0,因此在C程序的常常使用 int *p=NULL;让指针变量为空指针。

对指针变量赋0值和不赋值是不同的。指针变量未赋值时,可以是任意值,是不能使用的。否则将造成意外错误。而指针变量赋0值后,则可以使用,只是它不指向具体的变量而已。

例:教材p206

main()

{ int a,b,*p,*p1=&a,*p2=&b;

scanf("%d%d",p1,p2);

if(a<b){ p=p1; p1=p2; p2=p;}

printf("\na=%d, b=%d\n\n", a,b);

printf("max=%d, min=%d\n", *p1,*p2);

}

[程序演示]

slide23

main()

{ int a,b,*p,*p1=&a,*p2=&b;

scanf("%d%d",p1,p2);

if(a<b){ p=p1; p1=p2; p2=p;}

printf("\na=%d, b=%d\n\n", a,b);

printf("max=%d, min=%d\n", *p1,*p2);

}

p

p1

p1

a

a

&a

5

&a

5

p2

b

p2

b

&b

9

&b

9

slide24

四、指针变量作为函数参数

在第八章已学过:函数的参数可以是:整型、实型、字符型等数据。C语言中函数的参数还可以是指针类型,其作用是用来传递一个变量的地址。

例10.3 写一交换两个变量值的函数swap()

void swap(int *x, int *y)

{ int temp;

temp=*x; *x=*y; *y=temp;

}

main()

{ int a,b,*p,*p1=&a,*p2=&b;

scanf("%d%d",p1,p2);

printf("\na=%d, b=%d\n\n", a,b);

swap(p1,p2);

printf("\na=%d, b=%d\n\n", a,b);

}

slide25

p1

p1

a

p1

a

a

p1

a

&a

5

&a

5

&a

9

&a

9

p2

b

x

x

p2

b

&b

9

&a

&a

&b

5

调用前

p2

调用结束后

p2

b

b

&b

9

&b

5

y

y

&b

&b

调用时

在函数swap()中

程序的执行过程

slide26

若将swap函数写为如下:

指针变量在使用前

必须赋值!

void swap(int *x, int *y)

{ int *temp;

*temp=*x;

*x=*y;

*y=*temp;

}

此语句不对,因指针temp变量没有明确指向。

若将swap函数写为如下:

main()

{ int a,b;

scanf("%d%d",&a,&b);

printf("\na=%d, b=%d\n\n", a,b);

swap(a,b);

printf("\na=%d, b=%d\n\n", a,b);

}

void swap(int x, int y)

{ int temp;

temp=x;

x=y;

y=temp;

}

slide27

a

a

a

5

a

5

5

5

b

x

b

5

x

9

9

9

调用前

b

9

b

9

调用结束后

y

9

y

5

调用时

在函数swap()中

程序的执行过程

slide28

10.3 数组的指针和指向数组的指针变量

概念:

一个数组是由连续的一块内存单元组成的。C语言规定:数组名就是这块连续内存单元的首地址(称为数组的指针)。一个数组也是由各个数组元素(下标变量) 组成的。每个数组元素按其类型不同占有几个连续的内存单元。一个数组元素的首地址也是指它所占有的几个内存单元的首地址。

一个指针变量既可以指向一个数组,也可以指向一个数组元素, 可把数组名或第一个元素的地址赋予它。如要使指针变量指向第i号元素可以把i元素的首地址赋予它或把数组名加i 赋予它。

slide29

一、指向数组元素的指针

p,a,&a[0]

a[0]

1

p+1,a+1,&a[1]

a[1]

例:int a[10];

int *p=a;

p,a,&a[0]均指向同一单元,它们是数组a的首地址,也是0号元素a[0]的地址。

3

a[2]

5

a[3]

7

9

p+i,a+i,&a[i]

p+1,a+1,&a[1]均指向1号元素a[1]。

a[i]

类推可知p+i,a+i,&a[i]指向i号元素a[i]。

19

a[9]

应该说明的是p是指针变量,而a,&a[i]都是常量。在编程时应予以注意。

slide30

二、通过指针引用数组元素

引入指针变量后,就可以用两种方法来访问数组元素了。 第一种方法为下标法,即用a[i]形式访问数组元素。

第二种方法为指针法,即采用*(a+i)形式,用间接访问的方法来访问数组元素。

main()

{ int a[5],i,*pa=a;

for(i=0;i<5;i++)

{scanf("%d”, pa);

pa++;

}

pa=a;

for(i=0;i<5;i++)

{ printf("a[%d]=%d\n",i,*pa);

pa++;

}

}

main()

{ int a[5],i;

for(i=0;i<5;i++)

scanf("%d”, &a[i]);

for(i=0;i<5;i++)

printf("a[%d]=%d\n",i,a[i]);

}

slide31

main()

{ int a[5],i;

for(i=0;i<5;i++)

*(a+i)=i;

for(i=0;i<5;i++)

printf("a[%d]=%d\n",i,*(a+i));

}

三种方式的比较:教材Pg. 213。

(1)下表法比较直观,但执行效率低。

(2)a[i] 编译时转换为*(a+i) ,计算出元素的地址。

(3)使用指针变量,引用元素,因p++指向下一个元素,因执行效率较高。

slide32

使用指针变量要注意的几个问题:

1、指针变量可实现本身值的改变

例如: int a[10],*p=a

p++ 指向a[1]元素

可以使用下面语句来输入数组元素。

for(p=a;p<a+10;p++)

scanf("%d",p);

因使用指针变量引用数组元素时要注意指针变量当前的指向,否将出错。

2、数组名表示数组的首地址,是个地址常量,不出现如下运算:

×

×

×

a++; a=&a[i]; a=p;

slide33

例10.6 通过指针变量输入输出

a数组的10个元素。

p

a[0]

1

a[1]

3

a[2]

5

main()

{ int a[10],i,*p=a;

for(i=0;i<10;i++)

scanf("%d", p++);

printf("\n");

for(i=0;i<10;i++,p++)

printf("a[%d]=%d\n",i,*p);

}

a[3]

7

9

a[9]

p

------

------

------

分析上述程序中存在的问题?

slide34

注意指针变量的运算:

设有定义: int a[10],*p=a;

(1) p++ 指向下一个元,p的实际值加sizeof(int) 2,

(2) *p++ 等价于 *(p++)

(3) *(p++) 与 *(++p)不同

(4) (*p)++ 表示p当前所指向的元素加1

(5) 若:p=&a[i] 则:

*(p--) 相当于a[i--] *(--p) 相当于a[--i]

*(p++) 相当于a[i++] *(++p) 相当于a[++i]

p-a 的值为 i

slide35

例y7-2.c:利用指针实现将5个整数输入到数组a中,然后将a逆序复制到b中,并输出b中各单元的值 例y7-2.c:利用指针实现将5个整数输入到数组a中,然后将a逆序复制到b中,并输出b中各单元的值

main()

{ int a[5],b[5], i;

int *pa, *pb;

pa=a;

printf("Input the number\n",);

for(i=0;i<5;i++)

scanf("%d",pa++);

for(i=0;i<5;i++)

printf("a[%d]=%d",i,a[i]);

printf(" \n");

pa=a;

pb=b+4;

for(i=0;i<5;i++)

*pb--=*pa++;

for(i=0;i<5;i++)

printf(”b[%d]=%d",i,b[i]);

}

slide36

二、数组名和数组指针变量作函数参数

在第八章(函数)中曾经介绍过用数组名作函数的实参和形参的问题。在学习指针变量之后就更容易理解这个问题了。 数组名就是数组的首地址,实参向形参传送数组名实际上就是传送数组的地址, 形参得到该地址后也指向同一数组。

同样,指针变量的值也是地址,数组的指针即为数组的首地址,当然也可作为函数的参数使用。例:

float aver(float *pa);

main()

{ float sco[5],av,*sp;

int i;

sp=sco;

printf("\ninput 5 scores:\n");

for(i=0;i<5;i++) scanf("%f",&sco[i]);

av=aver(sp);

printf("average score is %5.2f",av);

}

float aver(float *pa)

{ int i;

float av,s=0;

for(i=0;i<5;i++)

s=s+*pa++;

av=s/5;

return av;

}

slide37

说明:在C语言中形参和实参都可使用指针变量和数组名:说明:在C语言中形参和实参都可使用指针变量和数组名:

1、当形参是数组时,要求对应的实参为:

同类型的数组名或指针变量

2、当形参是指针变量,要求对应的实参为:

同类型的指针变量或数组名

形式参数

指针变量

数组名

实参数

指针变量

数组名

例10.7 将数组a中的元素按相反顺序存放。

slide38

void inv(int x[],int n)

{ int t,i,j,m=(n-1)/2;

for(i=0;i<=m;i++)

j=n-i-1;

t=x[i];x[i]=x[j];x[j]=t;

}

main()

{ int i,a[10];

for (i=0;i<10;i++)

scanf("%d",&a[i]);

inv(a,10);

for (i=0;i<10;i++)

printf("%d ",a[i]);

}

void inv(int x[],int n)

{ int t,i,j,m=(n-1)/2;

for(i=0;i<=m;i++)

j=n-i-1;

t=x[i];x[i]=x[j];x[j]=t;

}

main()

{ int i,a[10],p=a;

for (i=0;i<10;i++)

scanf("%d",p++);

p=a;

inv(p,10);

for (i=0;i<10;i++)

printf("%d ",p++);

}

slide39

void inv(int *x,int n)

{ int t,i,j,m=(n-1)/2;

for(i=0;i<=m;i++)

j=n-i-1;

t=*(x+i);

*(x+i)=*(x+j);

*(x+j)=t;

}

main()

{ int i,a[10];

for (i=0;i<10;i++)

scanf("%d",&a[i]);

inv(a,10);

for (i=0;i<10;i++)

print("%d ",a[i]);

}

void inv(int *x,int n)

{ int t,i,j,m=(n-1)/2;

for(i=0;i<=m;i++)

j=n-i-1;

t=*(x+i);

*(x+i)=*(x+j);

*(x+j)=t;

}

main()

{ int i,a[10],p=a;

for (i=0;i<10;i++)

scanf("%d",p++);

p=a;

inv(p,10);

for (i=0;i<10;i++)

print("%d ",p++);

}

slide40

例p.219 10.8 从10个数中找出最大最小值

void max_min(int a[], int n,int *maxp, int *minp)

{ int i;

*maxp=*minp=a[0];

for(i=0; i<n; i++) {

if (a[i]>*maxp ) *maxp=a[i];

if (a[i]<*minp ) *minp=a[i];

}

}

main()

{ int i,max,min, number[10]={3,7,9,11,0,6,7,5,4,2};

max_min( ??? );

printf("\nmax=%d, min=%d \n“,max,min);

}

slide41

void max_min(int a[], int n,int *maxp, int *minp)

{ int i;

*maxp=*minp=a[0];

for(i=0; i<n; i++) {

if (a[i]>*maxp ) *maxp=a[i];

if (a[i]<*minp ) *minp=a[i];

}

}

main()

{ int i,max1,min1, number1[10]={3,7,9,11,0,6,7,5,4,2};

int max2,min2, number2[20]={3,7,9,11,0,6,7,5,4,2,43,5,34,56,23,41,31,93,23};

max_min(number1,10,max1,min1);

printf("\nmax=%d, min=%d \n”,max1,min1);

max_min(number2,20,max2,min2 );

printf("\nmax=%d, min=%d \n”, max2,min2);

}

slide42

四、指向多维数组的指针变量

(一)、多维数组地址的表示方法

若有定义:int a[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};

a[0]+2

数组名a为数组的首地址

2000

a[0]

a[0]+1

a[0]+3

2000

a

a[0]

0 1 2 3

4 5 6 7

89 10 11

2008

a+1

a[1]

2016

a+2

a[2]

假设数组的首地址为:2000

slide43

二维数组的地址表示:

a 二维数组名,数组首地址,0行首地址

a[0],*(a+0),*a,&a[0][0] 第0行第0列元素地址

a+1, &a[1] 第1行首地址

a[1],*(a+1),&a[1][0] 第1行第0列元素地址

a+i, &a[i] 第i行首地址

a[i], *(a+i), &a[i][0] 第i行首地址

#define PF "%d,%d,%d,%d,%d,\n"

main()

{ int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};

printf(PF,a,*a,a[0],&a[0],&a[0][0]);

printf(PF,a+1,*(a+1),a[1],&a[1],&a[1][0]);

printf(PF,a+2,*(a+2),a[2],&a[2],&a[2][0]);

printf("%d,%d\n",a[1]+1,*(a+1)+1);

printf("%d,%d\n",*(a[1]+1),*(*(a+1)+1));

}

slide44

表示形式

地址

含义

a

2000

二维数组名,数组首地址

2000

a[0],*(a+0),*a

第0行第0列元素地址

2008

a+1

第1行首地址

2008

第1行第0列元素地址

a[1],*(a+1)

2012

第1行第2列元素地址

a[1]+2,*(a+1)+2,&a[1][2]

第1行第2列元素值

6

*(a[1]+2),*(*(a+1)+2),a[1][2]

#define PF "%d,%d,%d,%d,%d,\n"

main()

{ int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};

printf(PF,a,*a,a[0],&a[0],&a[0][0]);

printf(PF,a+1,*(a+1),a[1],&a[1],&a[1][0]);

printf(PF,a+2,*(a+2),a[2],&a[2],&a[2][0]);

printf("%d,%d\n",a[1]+1,*(a+1)+1);

printf("%d,%d\n",*(a[1]+1),*(*(a+1)+1));

}

slide45

表示形式

地址

含义

a

2000

二维数组名,数组首地址

2000

a[0],*(a+0),*a

第0行第0列元素地址

2008

a+1

第1行首地址

2008

第1行第0列元素地址

a[1],*(a+1)

2012

第1行第2列元素地址

a[1]+2,*(a+1)+2,&a[1][2]

第1行第2列元素值

6

*(a[1]+2),*(*(a+1)+2),a[1][2]

设有定义:

int a[3][4],i,j;

引用二维数组元素的方法:

(1)下标法: a[i][j]

(2)指针法: *(*(a+i)+j)

slide46

(二)、多维数组的指针变量

1、指向数组元素的指针变量

设有定义:

int a[3][4],i,j;

int *p;

p=&a[0][0];

p为指向数组元素的指针变量,引用二维数组元素的方法:

p+1则表示指向当前元素的下一个元素。

元素a[i][j]的地址表示为: p+4*i+j

a[i][j]的值表示为: *(p+4*i+j)

如果一个n*m的二维数组的第i 行j列元素相对于首地址的增量为: i*m+j

slide47

例10.12 用指向数组元素 输出 m

main()

{ int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};

int i,j,*p;

p=&a[0][0];

for(i=0;i<12;i++)

{if (i%4==0) printf("\n");

printf("%2d ",*p++);

}

}

slide48

p

int a[3][4];

a[0][0]

a[0][1]

a[0][2]

a[0][3]

a[1][0]

a[1][1]

a[1][2]

a[1][3]

a[2][0]

a[2][1]

a[2][2]

a[2][3]

例 指向二维数组元素的指针变量

main()

{ static int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};

int *p;

for(p=a[0];p<a[0]+12;p++)

{ if((p-a[0])%4==0) printf("\n");

printf("%4d ",*p);

}

}

slide49

2、指向由m个元素组成的一维数组的指针变量

因为n×m的二维数组a 可分解为一维数组a[0],a[1],.. .a[n-1],而它们分别又是具有m个元素的一维数组。

因此可定义一个指向由m个元素组成的一维数组的指针变量来处理二维数组。把这个指针变量称为:行指针变量

行指针变量说明的一般形式为:

类型说明符 (*指针变量名)[长度]

例: int (*p)[4] 它表示p是一个指针变量,它指向由4个元素组成的一维数组,或说p可指向一个有4列的二维数组。

slide50

p

a

int a[3][4];

p[0]+1或 *p+1

a[0][0]

*(*p+1)或 (*p)[1]

a[0][1]

a[0][2]

p+1

a+1

a[0][3]

a[1][0]

p[1]+2或 *(p+1)+2

a[1][1]

*(*(p+1)+2)

a[1][2]

p+2

a+2

a[1][3]

a[2][0]

a[2][1]

a[2][2]

a[2][3]

  • 指向一维数组的指针变量
    • 定义形式: 数据类型 (*指针名)[一维数组维数];

例 int (*p)[4];

  • 可让p指向二维数组某一行

如 int a[3][4], (*p)[4]=a;

p的值是一维数组的

首地址,p是行指针

( )不能少

int (*p)[4]与int *p[4]不同

一维数组指针变量维数和

二维数组列数必须相同

slide51

int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};

int i,j, (*p)[4];

p=a;

*p+2

*p+0

数组名a为数组的首地址

*p+1

*p+3

a, p

a[0]

0 1 2 3

4 5 6 7

89 10 11

a+1, p+1

a[1]

a+2, p+2

a[2]

数组a的元素a[i]j]的表示:

*(*(a+i)+j), *(*(p+i)+j)

*(a[i]+j) , *(p[i]+j)

slide52

例10.12(a) 用行指针 输出

main()

{ int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};

int i,j,(*p)[4];

p=&a[0];

for(i=0;i<3;i++)

{

for(j=0;j<4;j++)

printf("%2d ",*(*(p+i)+j) );

printf("\n");

}

}

slide53

若int a[3][4];int (*p1)[4]=a;int *p2=a[0];

实参

形参

数组名a

数组名int x[][4]

数组名a

指针变量int (*q)[4]

指针变量p1

数组名int x[][4]

指针变量p1

指针变量int (*q)[4]

指针变量p2

指针变量int *q

3. 多维数组的指针作函数的参数

  • 二维数组的指针作函数参数
    • (1)用二维数组名
  • (2)用指向变量的指针变量
    • (3)用指向一维数组的指针变量
slide54

79

60

52

65

80

87

90

81

90

99

100

98

p

p

例10-14 3个学生各学4门课,计算总平均分,并输出第n个学生成绩

函数说明

void average(float *p,int n)

{ float *p_end, 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);

}

void search(float (*p)[4], int n)

{ int i;

printf(" No.%d :\n",n);

for(i=0;i<4;i++)

printf("%5.2f ",*(*(p+n)+i));

}

main()

{ void average(float *p,int n);

void search(float (*p)[4],int n);

float score[3][4]=

{{65,67,79,60},{80,87,90,81},

{90,99,100,98}};

average(*score,12);

search(score,2);

}

列指针

行指针

float p[][4]

p[n][i]

slide55

void search(float (*p)[4], int n)

{ int i,j,flag;

for(j=0;j<n;j++)

{ flag=0;

for(i=0;i<4;i++)

if(*(*(p+j)+i)<60) flag=1;

if(flag==1)

{ printf("No.%d is fail,his scores are:\n",j+1);

for(i=0;i<4;i++)

printf("%5.1f ",*(*(p+j)+i));

printf("\n");

}

}

}

p

70

60

57

65

58

87

90

81

90

99

100

98

main()

{ void search(float (*p)[4], int n);

float score[3][4]={{...},{...},{...}};

search(score,3);

}

例10-15 3个学生各学4门课,(计算总平均分,)并查找一门以上

课 不及格学生, 输出其各门课成绩

 p[j][i]

slide56

二维数组与一维数组指针变量的关系

如 int a[5][10] 与int (*p)[10];

  • 二维数组名是一个指向有10个元素的一维数组的指针常量
  • p=a+i 使 p指向二维数组的第i行
  • *(*(p+i)+j)  a[i][j]
  • 二维数组形参实际上是一维数组指针变量,

即 int x[ ][10]  int (*x)[10]

  • 变量定义(不是形参)时两者不等价
  • 系统只给p分配能保存一个指针值的内存区(一般2字节);而给a分配2*5*10字节的内存区
slide57

10.4 字符串的指针和指向字符串的指针变量

指向字符串的指针变量的定义与指向字符变量的指针变量说明是相同的。只能按对指针变量的赋值不同来区别。

对指向字符变量的指针变量应赋予该字符变量的地址。

如: char c,*p=&c; 表示p是一个指向字符变量c的指针变量。

而: char *s="C Language"; 则表示s是一个指向字符串的指针变量。把字符串的首地址赋予s。

例: main()

{ char *ps;

ps="C Language";

printf("%s",ps);

}

char *ps="C Language";

slide58

string

string[0]

I

string[1]

string[2]

l

string[3]

o

string[4]

v

string[5]

e

string[6]

string[7]

C

string[8]

h

string[9]

i

string[10]

n

string[11]

a

string[12]

!

string[13]

\0

  • 字符串表示形式
    • 用字符数组实现

例 main( )

{ char string[]=" I love China! ";

printf("%s\n",string);

printf("%s\n",string+7);

}

slide59

string

I

l

o

string

v

e

C

h

i

n

a

!

\0

  • 用字符指针实现

字符指针初始化:把字符串首地址赋给string

 char *string;

string=“I love China!”;

例10-16.c

main( )

{ char *string=" I love China! ";

printf("%s\n",string);

string+=7;

while(*string)

{ putchar(string[0]);

string++;

}

}

*string!=0

slide60

例:输出字符串中n个字符后的所有字符。

main()

{ char *ps="this is a book";

int n=10;

ps=ps+n;

printf("%s\n",ps);

}

运行结果为:

book

例:字符串的复制

main()

{ char a[]="this is a book",b[16];

int n;

for(n=0;a[n]!='\0';n++)

*(b+n)=*(a+n);

*(b+n)='\0';

printf("%s",b);

}

slide61

a

b

例:字符串的复制

main()

{ char a[]="this is a book" ;

char b[16],*p1,*p2;

p1=a;p2=b;

while(*p1!='\0')

*p2++=*p1++;

*p2='\0';

p2=b;

printf("%s",p2);

}

p1

p2

T

T

h

h

i

i

s

s

i

i

s

s

p1

p2

a

a

问能否将程序写成如下形式?

main()

{ char *p1="this is a book";

char *p2;

while(*p1!='\0')

. . . /* 以下与上面相同*/

}

b

b

o

o

o

o

k

k

\0

\0

slide62

例Y7-3:利用字符指针求字符串中各种字符的个数例Y7-3:利用字符指针求字符串中各种字符的个数

main()

{

char str[200];

int count[3]={0};

char *pstr;

char ch;

gets(str);

pstr=str;

while(*pstr!=0)

{

ch=*pstr;

ch=toupper(ch);

if(ch>='A'&&ch<='Z')

count[0]++;

else if(ch>='0'&&ch<='9')

count[1]++;

else

count[2]++;

pstr++;

} //while

printf(“this string contains\ %d letters, %d digits and %d\ other characters\n",

count[0],count[1],count[2]);

}

slide63

二、字符串指针作为函数的参数

把字符串指针作为函数参数的使用,传递字符串或字符数组的首地址。

1、当形参是字符数组时,要求对应的实参为:

字符数组名或字符指针变量

2、当形参是字符指针变量,要求对应的实参为:

字符指针变量或数组名

形式参数

字符指针变量

字符数组名

实参数

字符指针变量

字符数组名

slide64

把字符串指针作为函数参数的使用。

例:要求把一个字符串的内容复制到另一个字符串中,并且不能使用strcpy函数。

cpystr(char *pss,char *pds)

{ while((*pds=*pss)!='\0')

{ pds++;

pss++; }

}

main()

{ char *pa="CHINA",b[10],*pb;

pb=b;

cpystr(pa,pb);

printf("string a=%s\nstring b=%s\n",pa,pb);

}

while((*pds++=*pss++)!='\0');

slide65

使用字符数组和字符指针变量处理字符串时应注意的几个问题:使用字符数组和字符指针变量处理字符串时应注意的几个问题:

1 、字符串指针变量本身是一个变量,用于存放字符串的首地址。而字符串本身是存放在以该首地址为首的一块连续的内存空间中并以‘\0’作为串的结束。字符数组是由于若干个数组元素组成的,它可用来存放整个字符串。

2、对字符数组作初始化赋值,必须采用外部类型或静态类型, 如: static char st[]={“C Language”};

而对字符串指针变量则无此限制,如: char *ps="C Language";

3、 对字符串指针方式 char *ps="C Language";

可以写为: char *ps; ps="C Language";

而对数组方式: static char st[]={"C Language"};

不能写为: char st[20]; st={"C Language"};

而只能对字符数组的各元素逐个赋值。

slide66

字符指针变量与字符数组

char *cp; 与char str[20];

    • str由若干元素组成,每个元素放一个字符;而cp中存放字符串首地址
    • char str[20]; str=“I love China!”; ()

char *cp; cp=“I love China!”; ()

    • str是地址常量;cp是地址变量
    • cp接受键入字符串时,必须先开辟存储空间

例 char str[10];

scanf(“%s”,str); ()

而 char *cp;

scanf(“%s”, cp); ()

改为: char *cp,str[10];

cp=str;

scanf(“%s”,cp); ()

slide67

10.5 函数的指针和指向函数的指针变量

概念:在C语言中规定,一个函数总是占用一段连续的内存区, 而函数名就是该函数所占内存区的首地址。 我们可以把函数的首地址(或称入口地址)称为“函数的指针”,把函数的指针赋予一个指针变量,使该指针变量指向该函数。然后通过指针变量就可以找到并调用这个函数。 我们把这种指向函数的指针变量称为“指向函数的指针变量”,也称函数指针变量。

一、函数指针变量定义的一般形式为:

类型说明符 (*指针变量名)();

其中“类型说明符”表示被指函数的返回值的类型。

“(* 指针变量名)”表示“*”后面的变量是定义的指针变量。

最后的空括号表示指针变量所指的是一个函数。

slide68

max

指令1

指令2

…...

  • 函数指针:函数在编译时被分配的入口地址,用函数名表示
  • 指向函数的指针变量
    • 定义形式: 数据类型 (*指针变量名)();

如 int (*p)();

( )不能省

int (*p)() 与 int *p()不同

  • 函数指针变量赋值:如p=max;

专门存放函数入口地址

可指向返回值类型相同的不同函数

函数返回值的数据类型

  • 函数调用形式: c=max(a,b);  c=(*p)(a,b);  c=p (a,b);
  • 对函数指针变量pn, p++, p--无意义

函数指针变量指向的函数必须有函数说明

slide69

例如: int (*pf)();

表示pf是一个指向函数入口的指针变量,该函数的返回值(函数值)是整型。

下面通过例子来说明用指针形式实现对函数调用的方法。

int max(int a,int b)

{ if(a>b)return a;

else return b;

}

main()

{ int (*pmax)();

int x,y,z;

pmax=max;

printf("input two numbers:\n");

scanf("%d%d",&x,&y);

z=(*pmax)(x,y);

printf("maxmum=%d",z);

}

pmax

命令1

命令2

. . .

slide70

从上述程序可以看出,用函数指针变量形式调用函数的步骤如下:从上述程序可以看出,用函数指针变量形式调用函数的步骤如下:

1. 先定义函数指针变量,

如: int (*pmax)();定义 pmax为函数指针变量。

2. 把被调函数的入口地址(函数名)赋予该函数指针变量,如程序中的 pmax=max;

3. 用函数指针变量形式调用函数,如程序中 z=(*pmax)(x,y);

调用函数的一般形式为: (*指针变量名) (实参表)

使用函数指针变量还应注意以下两点:

a. 函数指针变量不能进行算术运算,这是与数组指针变量不同的。数组指针变量加减一个整数可使指针移动指向后面或前面的数组元素,而函数指针的移动是毫无意义的。

b. 函数调用中“(*指针变量名)”的两边的括号不可少,其中的*不应该理解为求值运算,在此处它只是一种表示符号。

(例P243)

slide71

void main()

{ int a,b,max(int,int),

min(int,int),add(int,int);

void process(int,int,int (*fun)());

scanf("%d,%d",&a,&b);

process(a,b,max);

process(a,b,min);

process(a,b,add);

}

void process(int x,int y,int (*fun)())

{ int result;

result=(*fun)(x,y);

printf("%d\n",result);

}

max(int x,int y)

{ printf(“max=”);

return(x>y?x:y);

}

min(int x,int y)

{ printf(“min=”);

return(x<y?x:y);

}

add(int x,int y)

{ printf(“sum=”);

return(x+y);

}

  • 二. 用函数指针变量作函数参数

例10-24 用函数指针变量作参数,求最大值、最小值和两数之和

slide72

10.6 返回指针值的函数

前面我们介绍过,所谓函数类型是指函数返回值的类型。 在C语言中允许一个函数的返回值是一个指针(即地址), 这种返回指针值的函数称为指针型函数。

定义指针型函数的一般形式为:

类型说明符 *函数名(形参表)

{

…… /*函数体*/

}

其中函数名之前加了“*”号表明这是一个指针型函数,即返回值是一个指针。类型说明符表示了返回的指针值所指向的数据类型。

slide73

如:

int *ap(int x,int y)

{

...... /*函数体*/

}

表示ap是一个返回指针值的指针型函数, 它返回的指针指向一个整型变量。

注意的是函数指针变量和指针型函数在写法和意义上的区别。如int (*p)()和int *p()是两个完全不同的量。

int (*p)()是一个变量说明,说明p 是一个指向函数入口的指针变量,该函数的返回值是整型量。

int *p()则不是变量说明而是函数说明,说明p是一个指针型函数,其返回值是一个指向整型量的指针,*p两边没有括号。

slide74

main()

{ int i;

char *day_name(int n);

printf("input Day No:\n");

scanf("%d",&i);

if(i<0) exit(1);

printf("Day No:%2d-->%s\n",i,day_name(i));

}

char *day_name(int n)

{char *name[]={ "Illegal day",

"Monday",

"Tuesday",

"Wednesday",

"Thursday",

"Friday",

"Saturday",

"Sunday"};

return((n<1||n>7) ? name[0] : name[n]);

}

slide75

p

p

p

p

score数组

pointer

60

70

80

90

pointer+1

56

89

67

88

34

78

90

66

main()

{ float score[][4]={{60,70,80,90},

{56,89,67,88},{34,78,90,66}};

float *search(float (*pointer)[4],int n), *p;

int i,m;

printf("Enter the number of student:");

scanf("%d",&m);

printf("The scores of No.%d are:\n",m);

p=search(score,m);

for(i=0;i<4;i++)

printf("%5.2f\t",*(p+i));

}

float *search(float (*pointer)[4], int n)

{float *pt;

pt=*(pointer+n);

return(pt);

}

  • 返回指针值的函数
    • 函数定义形式:

类型标识符 *函数名(参数表);

例 int *f(int x, int y)

例p.246

10-25 指针函数实现:有若干学生成绩,要求输入学生序号后,

能输出其全部成绩

slide76

10.7 指针数组和指向指针的指针

一、指针数组的概念

一个数组的元素值为指针则这个数组称为是指针数组。 指针数组是一组有序的指针的集合。 指针数组的所有元素都必须是具有相同存储类型和指向相同数据类型的指针变量。

指针数组说明的一般形式为:

类型说明符 *数组名[数组长度]

其中类型说明符为指针值所指向的变量的类型。

例如: int *pa[3];

表示pa是一个指针数组,它有三个数组元素, 每个元素值都是一个指针,指向整型变量。

slide77

int *pb[2]

pb[0]

pb[1]

int b[2][3]

int b[2][3]

int *pb[2]

1

1

pb[0]

2

2

pb[1]

3

3

2

2

4

4

赋值:

main()

{ int b[2][3],*pb[2];

pb[0]=b[0];

pb[1]=b[1];

……..

}

6

6

初始化:

main()

{ int b[2][3],*pb[ ]={b[0],b[1]};

……..

}

  • 用于处理二维数组或多个字符串
    • 指针数组
      • 定义:数组中的元素为指针变量
      • 定义形式:[存储类型]数据类型 *数组名[数组长度说明];

例 int *p[4];

  • 指针数组赋值与初始化

指针本身的存储类型

指针所指向变量的数据类型

区分int *p[4]与int (*p)[4]

slide79

输出12个月:

main()

{

int i;

for(i=0; i<13; i++)

printf("%s\n", month_name(i));

}

slide80

char *month_name(int n)

{ static char *name[]={

"Illegal month",

"January",

"February",

"March",

"April",

"May",

"June",

"July",

"August",

"September",

"October",

"November",

"December"

};

return((n<1||n>12)?name[0]:name[n]);

}

输出12个月:

main()

{

int i;

for(i=0; i<13; i++)

printf("%s\n", month_name(i));

}

slide81

例Y7-4a:输入多个学生的名字,按升序输出 (数组) *自学*

include <stdio.h>

#include <conio.h>

#define STUNUM 10

main()

{

char name[STUNUM][20];

char str[80];

int i,j,k,num;

num=0;

for(i=0;i<STUNUM;i++)

{

printf("input the name of the %dth student:",i+1);

gets(str);

if(str[0]==0)

break;

if(strlen(str)>19)

{

i--;

continue;

}

strcpy(name[i],str);

num++;

}

slide82

for(j=1;j<=num-1;j++)

{

k=num-j;

for(i=0;i<num-j;i++)

if(stricmp(name[i],name[k])>0)

k=i;

if(k!=num-j)

{

strcpy(str,name[k]);

strcpy(name[k],name[num-j]);

strcpy(name[num-j],str);

}

}

for(i=0;i<num;i++)

printf("%dth:%s\n",i+1,name[i]);

}

slide83

例Y7-4b:输入多个学生的名字,按升序输出 (指针)*自学*

{

printf("input the name of the %dth student:",i+1);

gets(str);

if(str[0]==0)

break;

if(strlen(str)>19)

{

i--;

continue;

}

strcpy(name[i],str);

num++;

}

for(i=0;i<num;i++)

pstr[i]=name[i];

#include <stdio.h>

#include <conio.h>

#define STUNUM 10

main()

{

char name[STUNUM][20];

char str[80];

char *pstr[STUNUM];

int i,j,k,num;

num=0;

for(i=0;i<STUNUM;i++)

slide84

for(j=1;j<=num-1;j++)

{

k=num-j;

for(i=0;i<num-j;i++)

if(stricmp(pstr[i],pstr[k])>0)

k=i;

if(k!=num-j)

{

char *ptmp;

ptmp=pstr[k];

pstr[k]=pstr[num-j];

pstr[num-j]=ptmp;

}

}

for(i=0;i<num;i++)

printf("%dth:%s\n",i+1,pstr[i]);

}

slide85

int b[2][3]

int *pb[2]

b[0][0] *pb[0]

1

pb[0]

b[0][1] *(pb[0]+1)

2

pb[1]

b[0][2] *(pb[0]+2)

3

b[1][0] *pb[1]

2

b[1][1] *(pb[1]+1)

4

b[1][2] *(pb[1]+2)

6

例10-26b 用指针数组处理二维数组*自学*

main()

{ int b[2][3],*pb[2];

int i,j;

for(i=0;i<2;i++)

for(j=0;j<3;j++)

b[i][j]=(i+1)*(j+1);

pb[0]=b[0];

pb[1]=b[1];

for(i=0;i<2;i++)

for(j=0;j<3;j++,pb[i]++)

printf("b[%d][%d]:%2d\n",i,j,*pb[i]);

}

slide86

例p.249 10-27:由字符指针数组处理多个字符串的问题 (zb33)

#include "string.h"

main()

{ void sort(char *name[],int n);

void print(char *name[],int n);

char *name[]={ "CHINA","AMERICA",

"AUSTRALIA", "FRANCE","GERMAN"};

int n=5;

sort(name,n);

print(name,n);

}

slide87

void sort(char *name[],int n)

{ char *pt; int i,j,k;

for(i=0;i<n-1;i++)

{ k=i;

for(j=i+1;j<n;j++)

if(strcmp(name[k],name[j])>0) k=j;

if(k!=i)

{ pt=name[i]; name[i]=name[k]; name[k]=pt; }

}

}

void print(char *name[],int n)

{ int i;

for (i=0;i<n;i++) printf("%s\n",name[i]);

}

slide88

二、指向指针的指针

指针数组名同样表示指针数组的首地址,是一个指针变量的地址,即是指针的指针。

指针变量在内存中仍有一个存储单元,该单元的地址,即指针的指针。如下图:

pp

p

a

&p

&a

10

指向指针的指针变量的定义:

int a, *p=a;**pp=&p;

类型说明符 **指针名

slide89

例p.252 10-29 输出a[5]

main()

{ static int a[5]={1,3,5,7,9};

int *num[5]={&a[0], &a[1], &a[2], &a[3], &a[4]};

int **p,i;

p=num;

for(i=0;i<5;i++)

{ printf("%d\n",**p);

p++;

}

}

slide90

三、main()函数的参数

前面介绍的main函数都是不带参数的。因此main 后的括号都是空括号。实际上,main函数可以带参数,这个参数可以认为是 main函数的形式参数。

C语言规定main函数的参数只能有两个, 习惯上这两个参数写为argc和argv。因此,main函数的函数头可写为:

main (argc,argv)

C语言还规定argc(第一个形参)必须是整型变量,argv( 第二个

形参)必须是指向字符串的指针数组。加上形参说明后,main函数的函数头应写为: main (argc,argv)

int argv;

char *argv[];

或写成: main (int argc,char *argv[])

slide91

说明:由于main函数不能被其它函数调用, 因此不可能在程序内部取得实际值。那么,在何处把实参值赋予main函数的形参呢?

实际上,main函数的参数值是从操作系统命令行上获得的。当我们要运行一个可执行文件时,在DOS提示符下键入文件名,再输入实际参数即可把这些实参传送到main的形参中去。

DOS提示符下命令行的一般形式为:

C:\>可执行文件名 参数 参数……;

注意:main 的两个形参和命令行中的参数在位置上不是一一对应的。因为,main的形参只有二个,而命令行中的参数个数原则上未加限制。argc参数表示了命令行中参数的个数(注意:文件名本身也算一个参数),argc的值是在输入命令行时由系统按实际参数的个数自动赋予的。

slide92

例如有命令行为:

C:\>E624 BASIC dbase FORTRAN

由于文件名E624本身也算一个参数,所以共有4个参数,因此argc取得的值为4。argv参数是字符串指针数组,其各元素值为命令行中各字符串(参数均按字符串处理)的首地址。 指针数组的长度即为参数个数。数组元素初值由系统自动赋予。

main(int argc,char *argv[])

{ while(argc-->1)

printf("%s\n",*++argv); }

本例是显示命令行中输入的参数

如果上例的可执行文件名为e24.exe,存放在A驱动器的盘内。因此输入的命令行为:

C:\>a:e24 BASIC dBASE FORTRAN 则运行结果为:

BASIC

dBASE

FORTRAN

slide93

例Y7-8:利用命令行参数输出星期一到星期日的英文名

*自学*

#include <stdio.h>

char *week_str[]=

{

"Monday",

"Tuesday",

"Wednesday",

"Thursday",

"Friday",

"Saturday",

"Sunday"

};

slide94

void main(int argc,char *argv[])

{

int k;

if(argc==2)

{

sscanf(argv[1],"%d",&k);

if(k>7)

{

printf("command line argument must be in [1..7]\n");

return;

}

printf("%s\n",week_str[k-1]);

}

else

{

printf("use this program like this: Y7-8 3\n");

}

}

slide95

指针的数据类型

含义

定义

int i;

定义整型变量i

p为指向整型数据的指针变量

int *p;

int a[n];

定义含n个元素的整型数组a

n个指向整型数据的指针变量组成的指针数组p

int *p[n];

int (*p)[n];

p为指向含n个元素的一维整型数组的指针变量

int f();

f为返回整型数的函数

int *p();

p为返回指针的函数,该指针指向一个整型数据

int (*p)();

p为指向函数的指针变量,该函数返回整型数

p为指针变量,它指向一个指向整型数据的指针变量

int **p;

slide96

指针数组

指向一维数组的指针

返回指针的函数

指向函数的指针,函数返回int型变量

指向函数的指针,函数返回int 型指针

函数指针数组,函数返回int型变量

函数指针数组,函数返回int型指针

例 下列定义的含义

(1)int *p[3];

(2)int (*p)[3];

(3)int *p(int);

(4)int (*p)(int);

(5)int *(*p)(int);

(6)int (*p[3])(int);

(7)int *(*p[3])(int);

slide97

实验8.1 解法一:

main()

{ int i, j, a[3][6], *p, imin=0, jmin=0, imax=0, jmax=0;

printf(“Please input the Array :\n”);

p=*a;

for(i=0;i<3;i++)

for(j=0;j<6;j++)

{ scanf(“%d”,p);

if (*p>a[imax][jmax]) { imax=i; jmax=j;}

else if (*p<a[imin][jmin]) { imin=i; jmin=j;}

p++;

}

printf(“The max is %d,”,a[imax][jmax]);

printf(“It is a[%d][%d]\n”,imax, jmax);

printf(“The min is %d,”,a[imin][jmin]);

printf(“It is a[%d][%d]\n”,imin, jmin);

}

slide98

实验8.1 解法二:

int max,min;

void max_min_value(int *p,int n)

{

int i;

int *p_end;

p_end=p+n;

max=*p;min=*p;

for(;p<p_end;p++)

{

if(*p > max) max=*p;

else if(*p<min) min=*p;

}

printf("\n===max=%d,min=%d\n",

max,min);

return;

}

main()

{

int i,j;

int a[3][6]=

{{11,2,3,4,56,67},

{3,4,5,7,8,9},

{12,25,35,58,98,100}};

max_min_value(*a,18);

printf("\nmax=%d,

min=%d\n",max,min);

}

slide99

实验8.1 解法三:

int max,min,q1,t1,q2,t2;

void max_min_value(int (*p)[6])

{int i,j;

max=min=*(*p);

for(i=0;i<3;i++)

for(j=0;j<6;j++)

if(*(*(p+i)+j)>max)

{max=*(*(p+i)+j);q1=i,t1=j; }

else if(*(*(p+i)+j)<min)

{min=*(*(p+i)+j);q2=i,t2=j; }

return;

}

main()

{int a[3][6]={{1,2,3,4,5,6},{7,8,9,10,11,12},

{13,14,15,16,17,18}};

max_min_value(a);

printf("max=%d,min=%d,

q1=%d,t1=%d.

q2=%d,t2=%d\n",

max,min,q1,t1,q2,t2);

}

slide100

实验8.1 解法四:

int max,min,q1,t1,q2,t2;

void max_min_value(int *p[3])

{int i,j;

max=min=**p;

for(i=0;i<3;i++)

for(j=0;j<6;j++)

if(*(p[i]+j)>max)

{max=*(p[i]+j);q1=i,t1=j; }

else if(*(p[i]+j)<min)

{min=*(p[i]+j);q2=i,t2=j; }

return;

}

slide101

main()

{int i,j,a[3][6]={{11,2,3,4,5,6},

{7,8,9,10,1,122},{13,14,15,16,17,18}};

int *p[3];

p[0]=a[0];

p[1]=a[1];

p[2]=a[2];

max_min_value(a);

printf("max=%d,min=%d,*q1=%d,*t1=%d.*q2=%d,*t2=%d\n",

max,min,q1,t1,q2,t2);

slide102

实验8.2 解法一:conv(int (*p)[3])

{ int i, j, t;

for(i=0;i<3;i++)

for(j=i;j<3;j++)

{ t=*(*(p+i)+j);

*(*(p+i)+j)=*(*(p+j)+i);

*(*(p+j)+i)=t; } }

main()

{ int a[3][3], i, j;

printf(“Please input the Array :\n”);

for(i=0;i<3;i++)

for(j=0;j<3;j++)

scanf(“%d”,&a[i][j]);

conv(a);

for(i=0;i<3;i++)

{ for(j=0;j<3;j++)

printf(“%4d”,a[i][j]);

printf(“\n”); } }

slide103

实验8.2 解法二:

main()

{int a[3][3]={{1,3,5},{7,9,11},{13,15,19}};

int *p,i;

p=&a[0][0];

move(*a); move(p);

for(i=0;i<3;i++)

printf("%d %d %d\n",a[i][0],a[i][1],a[i][2]);

}

move(int *p)

{int i,j,t;

for(i=0;i<3;i++)

for(j=i;j<3;j++)

{t=*(p+3*i+j);

*(p+3*i+j)=*(p+3*j+i);

*(p+3*j+i)=t;

}

}

slide104

一、判断题:

  • 设变量定义为
  • char s[]=“hello”,
  • 则数组s中有6个元素。
  • 2.a是一维数组名,数组元素a[1]还可以写作“*(a++)”
slide105

二、单选题:

  • 下列程序段的输出结果是——。
  • int c[]={1,7,12};
  • int *k=c+1;
  • printf(“%d”,*k++);
  • 2 B. 7 c.8 d.12
  • 2.下列程序段的输出结果是——。
  • char *st[]={“abcd”,”efgh”,”ijkl”,“mnop”},**p=st;
  • p++;
  • printf(*p+1);
  • cd B. fgh c.ijkl d.出错
  • 3.int a[3][4]; 与数组元素a[2][1]等价的是
  • *(a[2]+1) B. a[9]
  • c. *(a[1]+2) d. *(*a+2)+1
slide106

三、程序填空题:

1. 一维数组 函数

2. 一维数组指针 函数

3. 结构体

4. 文件

slide107

四、程序阅读题:

1. 一维数组 函数

二维数组

2. 一维数组指针 函数

二维数组指针 指导p.36 (2)

字符串指针

3. 结构体 链表

4. 文件

slide108

五、程序设计题:

一维数组 函数

(一维数组指针 函数)

1. 求1+1/2!+1/3!+…+1/n!

调用函数fact(n)计算n!

2.统计 字母 数字 其他字符个数