1、项目n 项目要求项目要求n 某企业对员工采用计件工资管理制度。通过编写程序某企业对员工采用计件工资管理制度。通过编写程序,要达到以下目的:了解员工的工作情况以及生产进度,要达到以下目的:了解员工的工作情况以及生产进度,记录记录10名员工某一天制作的产品数量,统计分析一天中制名员工某一天制作的产品数量,统计分析一天中制作产品最多的员工序号和产品数量,并对各员工制作的产作产品最多的员工序号和产品数量,并对各员工制作的产品数量由多到少顺序进行排序;统计一天中制作产品的总品数量由多到少顺序进行排序;统计一天中制作产品的总量和平均量,统计低于平均量的员工个数及员工序号,并量和平均量,统计低于平均量的员工
2、个数及员工序号,并友好提醒他们要加快进度。友好提醒他们要加快进度。n 项目目标项目目标n 了解指针的概念,熟悉数组、指针和函数的综合编程了解指针的概念,熟悉数组、指针和函数的综合编程方法。方法。项目n 项目任务项目任务 序号序号名称名称任务内容任务内容1输入产品数量地址、指针、指针变量2显示产品数量指针的算术运算3统计产品最多的员工和数量指针变量作为函数参数4显示产品数量排序指针与数组5统计总量与平均量指针与字符串6统计低于平均量员工指针数组n地址和指针的概念地址和指针的概念n变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量n数组与指针数组与指针n字符串与指针字符串与指针n指向函数
3、的指针指向函数的指针n返回指针值的函数返回指针值的函数n指针数组和指向指针的指针指针数组和指向指针的指针n指针小结指针小结0.本项目内容本项目内容3 3 4 4 1.地址和指针的概念地址和指针的概念程序中:int i;float k;内存中每个字节有一个编号内存中每个字节有一个编号-地址地址.2000200120022005内存02003ik 编译或函数调用时为其分配内存单元编译或函数调用时为其分配内存单元变量是对程序中数据存储空间的抽象n变量和地址变量和地址1.地址和指针的概念地址和指针的概念n直接访问和间接访问直接访问和间接访问n直接访问:按变量地址存取变量值直接访问:按变量地址存取变量值
4、n间接访问:通过存放变量地址的变量去访问变量间接访问:通过存放变量地址的变量去访问变量52000直接访问直接访问5间接访问间接访问530012000 5ixi2000200120022003200420053001 5+5102000 显然,显然,x与与i是通过是通过i的地址联系起来的,一个变的地址联系起来的,一个变量的地址量的地址称为该变量的称为该变量的指针指针。因此,。因此,i的指针的指针为为2000,而存放地址,而存放地址(指针指针)的变量叫做的变量叫做指针变量指针变量。如:如:x5 5 1.地址和指针的概念地址和指针的概念指针:一个变量的地址指针:一个变量的地址指针变量:专门存放变量地
5、址的变量指针变量:专门存放变量地址的变量.2000200420062005整型变量整型变量i10变量变量pi2001200220032000指针指针指针变量指针变量 变量的变量的内容内容 变量的变量的地址地址指针变量变量变量地址(指针)变量值指向地址存入指针变量6 6 2.变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量n指针变量的定义指针变量的定义 nint *p1;float*p2;该定义表示该定义表示p1、p2是指针变量,是指针变量,p1准备用来存放整准备用来存放整数单元的地址,数单元的地址,p2准备用来存放实数单元的地址。准备用来存放实数单元的地址。n通常将指针与其所指向的
6、对象这样表示:通常将指针与其所指向的对象这样表示:对象的地址对象的地址 P*p*p7 7 2.变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量例如:例如:void main()int a=10,*p;p=&a;printf(“%d”,*p);np中存放的是某个单元的地址,中存放的是某个单元的地址,*p表示那个表示那个单元(对象)。单元(对象)。10pa,*p a的地址的地址 8 8 2.变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量n用于指针运算的运算符:用于指针运算的运算符:n格式:格式:&变量变量 功能:取出指定变量功能:取出指定变量(存储单元存储单元)的地址,的
7、地址,结果为结果为地址地址。n格式:格式:*(地址表达式地址表达式)功能:得到某功能:得到某地址单元中的值,地址单元中的值,结果为结果为数据数据。n例如:例如:int a=10,*p;p=&a;n&与与*作用相反,级别相同,从右作用相反,级别相同,从右左运算。左运算。n使用使用*返回的是返回的是a的值,故可理解为的值,故可理解为*p是变量是变量a的别名,即:的别名,即:printf(“%d”,*p);=printf(“%d”,a);9 9 2.变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量n 指针的初始化:指针的初始化:n一般形式:一般形式:存储类型存储类型 数据类型数据类型 *
8、指针名指针名=初始地址值;初始地址值;n定义时,若未赋初值,编译自动赋初值定义时,若未赋初值,编译自动赋初值NULLNULL。NULL(大写大写)是一个符号常量,在是一个符号常量,在stdio.h文件中已定义。文件中已定义。n 例如:例如:int int*p,x;void p,x;void*q=NULL;q=NULL;nq中的地址值为中的地址值为0,p中是一个不确定的值中是一个不确定的值,若当作地址值引若当作地址值引用,这个地址中有可能存放的是系统重要数据,轻着破坏用,这个地址中有可能存放的是系统重要数据,轻着破坏程序的运行,重着导致系统瘫痪。程序的运行,重着导致系统瘫痪。1010 例 int
9、 i;int *p=&i;变量必须与已说明过的类型应一致例 int *p=&i;int i;2.变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量n指针变量的赋值:指针变量的赋值:n指针中只能存入由系统分配的地址,用户无权指针中只能存入由系统分配的地址,用户无权赋值,只能利用赋值,只能利用&取地址。取地址。n例:例:int x,*p1=&x,*p2,sz10;p2=sz;p1=&sz2;n注意:注意:int*p=123;/错误错误 p=&67;p1=&(i+5);/错误错误 只能取变量的地址只能取变量的地址 p=100;p=&a0;/错误错误1111 2.变量的指针和指向变量的指针变
10、量变量的指针和指向变量的指针变量【例例1】指针运算符的使用指针运算符的使用main()int a=2,*p;p=&a;printf(“%d%dn”,a,*p);*p=4;printf(“%d%dn”,a,*p);*p=*p+6;printf(“%d%d”,a,*p);【例例2】读结果读结果(学生练习学生练习)main()int b=5,*q=&b;printf(“%dn”,*q+10);if(*q10)printf(“%d”,b-5);else printf(“%d”,*q-10);运行结果是:运行结果是:2 24 410 10运行结果是:运行结果是:15-51212 2.变量的指针和指向变量
11、的指针变量变量的指针和指向变量的指针变量【例例3】交换两个数的值交换两个数的值main()int a=5,b=8;int t;printf(“a=%d,b=%d”,a,b);t=a;a=b;b=t;printf(“a=%d,b=%d”,a,b);【例例3】交换两个数的值(指针)交换两个数的值(指针)main()int a=5,b=8;int*pa=&a,*pb=&b;int t;printf(“a=%d,b=%d”,a,b);t=*pa;*pa=*pb;*pb=t;printf(“a=%d,b=%d”,a,b);1313 2.变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量main
12、()int a,b,t,*p,*q;p=&a;q=&b;scanf(“%d%d”,&a,&b);if(*p*q)t=*p;*p=*q;*q=t;printf(“%d%d”,a,b);【例例4 4】输入输入a,b的值的值,按大小顺序输出(学生练习)按大小顺序输出(学生练习)main()int a,b,*t,*p,*q;p=&a;q=&b;scanf(“%d%d”,&a,&b);if(*p*q)t=p;p=q;q=t;printf(“%d%d”,*p,*q);1414 2.变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量n指针变量做函数参数指针变量做函数参数-地址传递地址传递n特点:共
13、享内存,特点:共享内存,“双向双向”传递传递【例例5】利用函数,实现两个数的交换利用函数,实现两个数的交换void swap(int x,int y)int t;t=x;x=y;y=t;main()int a=5,b=8;swap(a,b);printf(“%d,%dn”,a,b);void swap(int*x,int*y)int t;t=*x;*x=*y;*y=t;main()int a=5,b=8;swap(&a,&b);printf(“%d,%dn”,a,b);值传递值传递地址传递地址传递运行结果是:运行结果是:5,8运行结果是:运行结果是:8,51515 2.小测验小测验【例例1】执
14、行下面程序段后,执行下面程序段后,a的值为:的值为:int a=10,b=1,*p;p=&a;a=*p+b;A)12B)11C)10D)有错有错【例例2】下面程序的运行结果为:下面程序的运行结果为:void fun(int*a,int*b)int*k;k=a;a=b;b=k;main()int a=3,b=6,*x=&a,*y=&b;fun(x,y);printf(“%d%d”,a,b);A)6,3B)3,6C)0,0D)有错有错1616 3.数组与指针数组与指针n 数组的指针:数组的起始地址数组的指针:数组的起始地址n 数组元素的指针:数组元素的地址数组元素的指针:数组元素的地址n 数组名可
15、视为地址常量数组名可视为地址常量n例如:例如:int a 10;int *pa;pa=&a 0;/pa=a;当指针与数组建立了联系后,就可用指针来表示元素及其当指针与数组建立了联系后,就可用指针来表示元素及其地址:地址:pa=a pa0=a0 pa+1=a+1 pa1=a1 pa+4=a+4 pa4=a4 pa+n表示数组第表示数组第n个数据的地址,即个数据的地址,即 pa+n=&an *(pa+n)是是an1717 表明指针表明指针pa指向数组指向数组a的首地址的首地址;此时此时,指针对象,指针对象*pa为为a0;1818 3.数组与指针数组与指针数组元素表示方法数组元素表示方法a0a1a2
16、a3a9.aa+9a+1a+2地址元素下标法a0a1a2a9a0a1a2a3a9.pp+9p+1p+2地址元素指针法*p*(p+1)*(p+2)*(p+9)变址运算符ai *(a+i)ai pi *(p+i)*(a+i)*a*(a+1)*(a+2)*(a+9)p0p1p2p93.数组与指针数组与指针n 对数组的三种访问方式对数组的三种访问方式n例如:例如:int a5,i,*p;for(i=0;i5;i+)scanf(“%d”,&ai);下标访问法下标访问法 for(i=0;i5;i+)scanf(%d,(a+i);地址计算法地址计算法 for(p=a;p(a+5);p+)scanf(“%d”
17、,*p);指针法指针法n三种访问方式的比较:三种访问方式的比较:下标访问法:适合随机访问数组元素。下标访问法:适合随机访问数组元素。地址访问法:程序中直接给出了地址,速度快;地址访问法:程序中直接给出了地址,速度快;但因数组名中但因数组名中的地址值不能改变,使用不方便,缺乏灵活。的地址值不能改变,使用不方便,缺乏灵活。指针访问法:访问速度更快,使用灵活,简洁。指针访问法:访问速度更快,使用灵活,简洁。1919 3.数组与指针数组与指针【例例6】利用指针方法访问数组利用指针方法访问数组main()int a10,i,*p;for(i=0;i10;i+)ai=i;p=a;for(i=0;i10;i
18、+)printf(“%d”,*p+);【例例6】main()int a10,i,*p;for(i=0;i10;i+)ai=i;for(p=a;pa+10;p+)printf(“%d”,*p);2020 3.数组与指针数组与指针【例例7】给定给定10个整数,求最大值。(指针方法访问数组)个整数,求最大值。(指针方法访问数组)(学生练习学生练习)#include “stdio.h”#define N 10main()int aN=5,7,3,6,2,1,8,9,4,0;int i,*p,max;p=a;max=*(p+);for(i=1;imax)max=*p ;printf (“max=%d n
19、“,max);思考:思考:若若 p=a;*p+与与*(p+)有何区别?有何区别?*p+与与(*p)+有何区别?有何区别?*p+与与*(+p)有何区别?有何区别?*p+与与*(p+1)有何区别?有何区别?*(p+5)的值是多少?的值是多少?2121 3.数组与指针数组与指针n数组名作函数参数数组名作函数参数n函数调用时,数组作为函数参数,有两种类型:函数调用时,数组作为函数参数,有两种类型:数组元素数组元素作函数参数和作函数参数和数组名数组名作函数参数。作函数参数。数组元素作函数参数同普通变量一样。数组元素作函数参数同普通变量一样。数组名数组名代表数组代表数组首地址首地址-即指针即指针,所以数组
20、名可以作,所以数组名可以作为实参和形参使用,同时配合指针变量作为实参和为实参和形参使用,同时配合指针变量作为实参和形参,即可利用指针方法对数组进行各种操作。形参,即可利用指针方法对数组进行各种操作。2222 3.数组与指针数组与指针【例例8】利用数组名作实参,指针变量作形参使数组元素按相利用数组名作实参,指针变量作形参使数组元素按相反顺序存放反顺序存放void inv(int*x)int*i,*j,*p,t;i=x;j=x+9;p=x+4;for(;i=p;i+,j-)t=*i;*i=*j;*j=t;main()int a10=3,5,7,9,11,0,6,7,5,4;int k;inv(a)
21、;for(k=0;k10;k+)printf(“%d ”,ak);程序的运行结果是:程序的运行结果是:4 5 7 6 0 11 9 7 5 32323 3.数组与指针数组与指针n指向多维数组的指针指向多维数组的指针n多维数组的地址(以二维数组多维数组的地址(以二维数组a34为例)为例)a34包含包含3行,每行又是一个一维数组:行,每行又是一个一维数组:a0,a1,a2,每个一维数组又包含,每个一维数组又包含4个元素。个元素。a代表整个二维数组的首地址,代表整个二维数组的首地址,a+1代表第代表第1行首地址行首地址a,a0,*(a+0),&a00等价,同理等价,同理 a+i,ai,*(a+i),
22、&ai0等价,那么等价,那么 ai+j,*(a+i)+j,&aij表示第表示第i行第行第j列的元素地址列的元素地址n指向多维数组的指针变量指向多维数组的指针变量设设p为指向二维数组为指向二维数组a的指针变量,有的指针变量,有p=a。p+i则指向则指向ai,*(p+i)+j是二维数组是二维数组i行行j列的元素地址列的元素地址 2424 3.数组与指针数组与指针【例例9】读结果(学生练习)读结果(学生练习)main()int a33,*p,i;p=&a00;for(i=0;i9;i+)pi=i+1;printf(“%dn”,a12);for循环实现给二维数组循环实现给二维数组中的中的9个元素赋个元
23、素赋值:值:.,p5=6,即即a12的值为的值为6运行结果是:运行结果是:62525 3.小测验小测验【例例1】有定义:有定义:int a8;则以下表达式中不能代表数组元素则以下表达式中不能代表数组元素a1地址的是:地址的是:A)&a0+1 B)&a1 C)&a0+D)a+1【例例2】有定义:有定义:int a=0,1,2,3,4,5,6,7,8,9,*p=a,i;其中其中0=i=9,则对则对a数组元素不正确的引用是:数组元素不正确的引用是:A)ap-a B)*(&ai)C)pi D)a10【例例3】以下程序的输出结果是:以下程序的输出结果是:main()int arr=30,25,20,15
24、,10,5,*p=arr;p+;printf(“%dn”,*(p+3);102626 4.字符串与指针字符串与指针n字符串的表示形式字符串的表示形式 n在在C程序中程序中,可以用两种方法访问一个字符串可以用两种方法访问一个字符串用字符数组存放一个字符串用字符数组存放一个字符串,然后输出该字符串然后输出该字符串如如:char string=“I love China!”;printf(“%sn”,string);或或puts(string);用字符指针指向一个字符串用字符指针指向一个字符串如如:char *string=“I love China!”;printf(“%sn”,string);或
25、或puts(string);注意注意:字符串指针只能利用赋值,且字符串指针中字符串指针只能利用赋值,且字符串指针中存放的仅是字符串首地址。存放的仅是字符串首地址。2727 4.字符串与指针字符串与指针n练习练习:n设设char*city,*name,*t;,判断下列语句是否正确判断下列语句是否正确 gets(city);scanf(“%s”,name);strcpy(t,city);错!无存储单元,接收的字符无地方可错!无存储单元,接收的字符无地方可存;故若利用函数赋值字符串,只能存;故若利用函数赋值字符串,只能借助于数组。借助于数组。2828 4.字符串与指针字符串与指针【例例10】利用字符
26、串指针完成字符串的复制利用字符串指针完成字符串的复制main()char a=“abcdefg”,b10,*p1,*p2;p1=a;p2=b;while(*p1!=0)*p2=*p1;p1+;p2+;*p2=0;puts(b);【例例1111】利用多种字符串指针方法完成字符串的复制利用多种字符串指针方法完成字符串的复制?(?(学生学生练习练习)方法之一方法之一:for(;*p1;p1+,p2+)*p2=*p1;*p2=0;方法之二方法之二:while(*p2+=*p1+);2929 4.字符串与指针字符串与指针【例例12】将字符串将字符串b连接到字符串连接到字符串a的后面的后面#include
27、main()char a30=computer;char b=language,*p,*q;p=a;q=b;while(*p!=0)p+;while(*q!=0)*p+=*q+;*p=0;p=a;printf(%sn,p);3030 4.小测验小测验【例例1】以下程序的输出结果是:以下程序的输出结果是:main()char b18=“abcdefg”,b28,*pb=b1+3;while(-pb=b1)strcpy(b2,pb);printf(“%dn”,strlen(b2);73131 8.指针小结指针小结n 有关指针的数据类型:有关指针的数据类型:n int i;.定义整型变量定义整型变量
28、i;n int *p;.p为指向整型数据的指针变量;为指向整型数据的指针变量;n int an;定义整型数组定义整型数组a,它有,它有n个元素;个元素;n int *pn;.定义指针数组定义指针数组p,它由,它由n个指向整型数据指针元素组成;个指向整型数据指针元素组成;n int (*p)n;p为指向含为指向含n个元素的一维数组的指针变量;个元素的一维数组的指针变量;n int f();.f为带回整型函数值的函数;为带回整型函数值的函数;n int *p();p为带回一个指针的函数,该指针指向整型数据;为带回一个指针的函数,该指针指向整型数据;n int (*p)();.p为指向函数的指针,该
29、函数返回一个整型值;为指向函数的指针,该函数返回一个整型值;n int *p;.p是一个指针变量,它指向一个指向整型数据的指针是一个指针变量,它指向一个指向整型数据的指针变量。变量。3232 例 下列定义的含义(1)int *p3;(2)int (*p)3;(3)int *p(int);(4)int (*p)(int);(5)int *(*p)(int);(6)int(*p3)(int);(7)int *(*p3)(int);函数指针数组,函数返回int型指针指针数组指向一维数组的指针返回指针的函数指向函数的指针,函数返回int型变量指向函数的指针,函数返回int 型指针函数指针数组,函数返回
30、int型变量8.指针小结指针小结3333 实验实验 8 8 指指 针针【实验目的实验目的】(1)(1)掌握指针的概念,会定义和使用指针变量掌握指针的概念,会定义和使用指针变量(2)(2)正确使用数组的指针和指向数组的指针变量正确使用数组的指针和指向数组的指针变量(3)(3)正确使用字符串的指针和指向字符串的指针变量正确使用字符串的指针和指向字符串的指针变量【实验内容实验内容】P265 8.1P265 8.1 P266 8.10 P266 8.10 10.1 输入输入3个整数,按由小到大输出个整数,按由小到大输出main()main()int n1,n2,n3;int n1,n2,n3;int
31、int*p1,p1,*p2,p2,*p3;p3;printf(printf(“enter 3 integers n1,n2,n3:enter 3 integers n1,n2,n3:”););scanf(scanf(“%d,%d,%d%d,%d,%d”,&n1,&n2,&n3);,&n1,&n2,&n3);p1=&n1;p2=&n2;p3=&n3;p1=&n1;p2=&n2;p3=&n3;if(n1n2)swap(p1,p2);if(n1n2)swap(p1,p2);if(n1n3)swap(p1,p3);if(n1n3)swap(p1,p3);if(n2n3)swap(p2,p3);if(n2n3)swap(p2,p3);printf(printf(“%d,%d,%dn%d,%d,%dn”,n1,n2,n3);,n1,n2,n3);swap(p1,p2)swap(p1,p2)int int*p1,p1,*p2;p2;int p;int p;p=p=*p1;p1;*p1=p1=*p2;p2;*p2=pp2=p 3535