版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第9章指针C语言程序设计数据类型根本类型构造类型指针类型空类型整型字符型实型长整型根本整型短整型无符号整型单精度型双精度型枚举类型数组类型结构体类型共用体类型2024/3/13《C语言程序设计》-第九章3指针的作用:
可以使程序简洁、紧凑、高效;有效地表示和使用复杂的数据结构;动态分配内存单元;方便地使用字符串;能得到多于一个的函数值。2024/3/13《C语言程序设计》-第九章4
9.5
指针与结构体9.4
指针与函数9.3指针与数组9.2变量的指针与指针变量9.1指针及指针变量的概念9.6
链表第9章指针
学习重点:1.指针、指针变量的概念。2.变量的指针及指向变量的指针变量的定义和使用;3.数组的指针和指向数组的指针变量的用法;4.字符串的指针和指向字符串的指针变量的用法;5.二级指针和指针数组的定义和使用方法;6.指针在函数中的应用。2024/3/13《C语言程序设计》-第九章6
学习难点:1.字符串的指针和指向字符串的指针变量;2.二级指针和指针数组;2024/3/13《C语言程序设计》-第九章79.1指针及指针变量的概念9.1.2指针变量和指针的类型9.1.1变量和地址美美的家小强的家
房间—变量名
9.1.1变量和地址
一个变量名代表内存中的一个存储单元,每个存储单元都有一个编号,这就是“地址”。房客—变量值101房间号—变量地址10253‘H’3.14ijchf……………………2000200220042005200920012003200620072008变量名是对程序中数据存储空间的抽象
inti,j;charch;floatf;i=5;j=3;ch=‘H’;f=3.14;
注意:内存单元的地址和内存单元的内容的区别。变量的地址是其所占存储单元的首地址。2024/3/13《C语言程序设计》-第九章10
访问变量有两种方式:(1)直接访问方式按变量的地址存取变量值的方式。如:inti;
scanf(“%d”,&i);i=i+3;
printf(“%d”,i);
间接访问方式由地址变量访问变量的方式。将变量〔比方i〕的地址存放在另一个变量(比方pi)中,然后通过变量pi来访问i的值。
pi称为地址变量。2000
pii2000H2000Hi由上可知,要使i=3,有两种方法,用图表示为:33
地址存储单元
&ii
2024/3/13《C语言程序设计》-第九章13…...…...2000200420062005整型变量i10变量pi200120022003指针:地址。2000指针指针变量
变量的地址inti;i=10;指针变量变量其它变量的地址(指针)变量值指向地址存入指针变量指针变量:专门存放内存单元的地址的变量。思考:抽屉的钥匙、身份证号码可否称为指针?9.1.2指针变量和指针的类型2024/3/13《C语言程序设计》-第九章159.1.2指针变量和指针的类型指针变量和其他的变量一样代表内存中的存储单元,指针变量的值是地址值,而变量的值是数据;一个指针变量只允许存放指定类型变量的地址。它允许存放哪种类型变量的地址,取决于对它的类型说明。2024/3/13《C语言程序设计》-第九章169.2变量的指针与指针变量9.2.3指针运算9.2.2指针变量的初始化9.2.1指针变量的定义及使用9.2.1指针变量的定义及使用[存储类型]数据类型
*指针变量名;指针变量本身的存储类型目标变量的数据类型表示定义指针变量不是‘*’运算符注意:(1)int*pi,*pj;
指针变量名是pi,pj,不是*pi,*pj。(2)指针变量只能指向定义时所规定类型的变量。
inti,j,*pi,*pj;floatf;float*pf;指针变量的定义:&与*运算符含义:取变量的地址单目运算符优先级:2结合性:右结合含义:
取指针所指向的存储单元。单目运算符优先级:2结合性:右结合…...…...2000200420062005i10p2001200220032000指针变量200010pi,*p2000p=
=
&i==
&(*p)i
==*p==*(&i)指针变量的使用2024/3/13《C语言程序设计》-第九章19思考:以下哪种是直接访问?哪种是间接访问?例
i=3;指针变量…...…...2000200420062005整型变量i10变量p20012002200320003例*p=3;32024/3/13《C语言程序设计》-第九章20[例9.1]指针的运用。main(){inti,j;int*pi,*pj;i=2;j=4;pi=&i;pj=&j;printf("%d,%d\n",*pi,*pj);printf("%u,%u\n",pi,pj);i=*pj+1;*pj=*pj+2;printf("%d,%d\n",i,j);printf("%d,%d\n",*pi,*pj);}2,465500,655025,65,6main(){intx,y,*px,*py,*p;scanf("%d%d",&x,&y);px=&x;py=&y;if(x<y){p=px;px=py;py=p;}
printf("MAX=%d,MIN=%d\n",*px,*py);}[例9.2]输入x、y两个整数,按先大后小的顺序输出x、y。69
输入MAX=9,MIN=62024/3/13《C语言程序设计》-第九章22复习与思考181、系统最终是通过什么对变量进行存取的?2、什么是指针?3、什么是指针变量?如何定义?4、指针运算符“*”的含义?如何进行间接访问?2024/3/13《C语言程序设计》-第九章239.2.2指针变量的初始化一般形式:[存储类型]
数据类型*指针变量名=地址值;例inti;int*p=&i;int*q=p;int*r=0;等价于int*r=NULL;例main(){inti=10;int*p;
*p=i;printf(“%d”,*p);}危险!例
main(){inti=10,k;int*p;
p=&k;*p=i;printf(“%d”,*p);}指针变量必须先赋值,再使用…...…...2000200420062005i10p200120022003随机2024/3/13《C语言程序设计》-第九章251.指针的赋值运算。例:inti,array[10],*p,*p1,*p2;p=&i;/*将变量
i的地址p*/p=array;/*将数组array首地址p*/p=&array[i];/*将数组元素地址p*/p1=p;/*指针变量p值p1*/p2=0;/*空指针,相当于p2=NULL;*/
p2=4000;/*地址值4000
p2*/
9.2.3指针运算2.指针与整数的加减运算:(1)指针变量自增或自减运算:++p,
p++:是使指针p向前移动一个所指单元。
--p,p--:
是使指针p向后移动一个所指单元。例inta[10];int*p=&a[0];p++;/*p=p+1;*/那么p指向a[1]。P+1的值实际上为p+1*2,即p+1*sizeof(a[0])2024/3/13《C语言程序设计》-第九章272.指针与整数的加减运算:假设p=&i;那么pn&in*sizeof(i)例:p指向int型数组,且p=&a[0];那么p+2指向a[2](2)指针变量加上或减去一个整数n,即p
n:其含义是指针由当前位置向前或向后移动n个所指单元。2024/3/13《C语言程序设计》-第九章282.指针与整数的加减运算:(3)指针相减:一般情况下,进行相减的两个指针变量应指向同一类型的数据,其相减的含义为两个指针变量所夹的元素个数加1。例如:
inta[5],*p1=a,*p2=&a[2];printf(“%d\n”,p2-p1);
输出结果为2(两下标的差)。=(p2-p1)/2(p2-p1)/sizeof(int)两个指针相加无意义。2024/3/13《C语言程序设计》-第九章29表示两个指针所指向的存储单元的相对位置。假设px和py指向同一数组,那么假设px<py,表示px指的元素在前假设px>py,表示px指的元素在后假设px==py表示px与py指向同一存储单元假设px==0表示px为空指针px==NULL假设p1与p2不指向同一数组,比较无意义3.指针的关系运算:2024/3/13《C语言程序设计》-第九章30[例9.3]求字符串的长度。main(){chars[256];char*p;scanf("%s",s);p=s;while(*p!='\0')p++;printf("Thestringlengthis%d\n",p-s);}9.3指针与数组9.3.4指针与多维数组9.3.3多级指针及指针数组9.3.2字符指针与字符数组9.3.1指向数组的指针9.3.1指向数组的指针例如,
inta[10],*p;
p=a;
p=&a[0];
p即为指向数组的指针。a[0]a[1]a[2]a[3]a[9]...整型指针p&a[0]p数组名:是表示数组首地址的地址常量。数组的指针:是指数组所占连续存储单元的首地址(即第一个元素的地址)。或
inta[10],*p=a;或
inta[10],*p=&a[0];数组元素的四种表示方法:a[i]
*(a+i)
*(p+i)
p[i]
*a*(a+1)*(a+2)*(a+9)a[0]a[1]a[2]a[3]a[9]...aa+9a+1a+2地址元素下标法a[0]a[1]a[2]a[9]指针法a[0]a[1]a[2]a[3]a[9]...pp+9p+1p+2地址元素*p*(p+1)*(p+2)*(p+9)p[0]p[1]p[2]p[9]a和p的区别:数组名a是地址常量,不可实现其自身的改变,如a++或&a非法;而数组指针p是地址变量,p++和&p合法。[]:是变址运算符,如a[i],是先按a+i计算地址,然后找出此地址指向的单元,即*(a+i).a[i]
*(a+i)...a[0]a[1]a[2]a[9][例9.5]对数组元素的访问。main(){inta[10];inti,*p;for(i=0;i<10;i++)scanf("%d",&a[i]);for(i=0;i<10;i++)printf("%4d",a[i]);printf("\n");for(i=0;i<10;i++)printf("%4d",*(a+i));printf("\n");for(p=a;p<(a+10);p++)printf("%4d",*p);printf("\n");}12310pppp[例9.6]程序越界举例。#include"stdio.h"main(){int*p,i,a[10];p=a;for(i=0;i<10;i++)scanf("%d",p++);printf("\n");for(i=0;i<10;i++,p++)printf("%u",*p);}运行输入:1234567890运行结果:655162851655141592655180149152159623619正确的程序应是:#include"stdio.h"main(){int*p,i,a[10];p=a;for(i=0;i<10;i++)scanf("%d",p++);printf("\n");
p=a;/*加此语句后程序不越界*/for(i=0;i<10;i++,p++)printf("%u",*p);}[例9.7]使用指针变量举例。#include"stdio.h"inta[]={0,1,2,3,4};main(){inti,*p;for(i=0;i<=4;i++)printf("%d\t",a[i]);putchar('\n');for(p=&a[0];p<=&a[4];p++)printf("%d\t",*p);putchar('\n');for(p=&a[0],i=1;i<=5;i++)printf("%d\t",p[i]);putchar('\n');for(p=a,i=0;p+i<=a+4;p++,i++)printf("%d\t",*(p+i));putchar('\n');}a[0]a[1]a[2]a[3]a[4]01234p0123401234123425637024注意比照[例9.8]指针变量举例。#include"stdio.h"inta[]={0,1,2,3,4};main(){inti,*p;for(p=a+4;p>=a;p--)printf("%d\t",*p);putchar(’\n’);for(p=a+4,i=0;i<=4;i++)printf("%d\t",p[-i]);putchar(’\n’);for(p=a+4;p>=a;p--)printf("%d\t",a[p-a]);putchar(’\n’);}运行结果:4321043210432102024/3/13《C语言程序设计》-第九章38指针变量运算时要注意以下表达式的含义假设inta[10],*p=a;*p++,*(p++)(*p)++*(++p),*++p...a[0]a[1]a[2]a[9]pppp123102024/3/13《C语言程序设计》-第九章39复习与思考191、什么是数组的指针和指向数组的指针变量?2、如何通过指针变量间接访问数组元素?3、假设p为指针变量,那么p++、++p、p±n的含义是什么?字符串表示形式:1、字符数组方式[例9.9]
main(){staticchars1[]="IloveChina!";printf("%s\n%c\t%c\n",s1,s1[0],*(s1+3));}IloveChis1[0]s1[1]s1[2]s1[3]s1[4]s1[5]s1[6]s1[7]s1[8]s1[9]s1s1[10]s1[11]s1[12]s1[13]n!a\0IloveChina!Io9.3.2字符指针与字符数组
[例9.10]
main(){char*s2="IloveChina!";char*s3,c;char*s4="w";s3=&c;*s3='H';printf("%s\n",s2);s2=s2+2;printf("%s\t%c\t%s\n",s2,*s3,s4);}ILoveChin!a\0w\0s4cs2字符指针初始化:把字符串首地址赋给s2char*s2;s2=“IloveChina!”;字符串的值是其首地址。s2ILoveChina!LoveChina!HwHs32、字符指针方式[例9.11]用数组方法将字符串a复制到字符串b。main(){chara[]="Iamaboy.",b[20];inti;for(i=0;a[i]!='\0';i++)b[i]=a[i];b[i]='\0';printf("Stringais:%s\n",a);printf("Stringbia:%s\n",b);}Stringais:Iamaboy.Stringbis:Iamaboy.[例9.12]用指针变量法将字符串a复制到字符串b。Stringais:Iamaboy.Stringbis:Iamaboy.main(){chara[]="Iamaboy.",b[20],*p1,*p2;inti;p1=a;p2=b;for(;*p1!='\0';p1++,p2++)*p2=*p1;*p2='\0';printf("Stringais:%s\n",a);printf("Stringbis:%s\n",b);}[例9.13]复制字符串。main(){chara[]="Iamaboy.",*b;b=a;printf("Stringais:%s\n",a);printf("Stringbis:%s\n",b);}使用字符数组与字符指针要注意:对字符数组整体赋值只能在初始化时进行;而对指针变量赋值,既可在初始化时进行,又可在其它地方赋值。str是地址常量,cp是地址变量,cp接受键入字符串时,必须先开辟存储空间。例charstr[10];scanf(“%s”,str);(
)而char*cp;scanf(“%s”,cp);(
)改为:char*cp,str[10];cp=str;scanf(“%s”,cp);(
)charstr[20];str=“IloveChina!”;(
)char*cp;cp=“IloveChina!”;(
)其根本区别就在于数组名是常量,而字符指针是变量。虽然字符指针也可以作为数组名,但它是地址变量,而字符数组是地址常量。多级指针及指针数组多级指针:指向指针的指针。一级指针:指针变量中存放目标变量的地址。二级指针:指针变量中存放一级指针变量的地址。定义形式:[存储类型]数据类型**指针名;pp&p&i123p(指针变量)i(整型变量)例inti=123;
int*p;
int**pp;
p=&i;pp=&p;目标变量一级指针二级指针多级指针及指针数组多级指针:指向指针的指针。一级指针:指针变量中存放目标变量的地址。二级指针:指针变量中存放一级指针变量的地址。多级指针的定义:定义指针变量时,标识符前有多少个*,即表示多少级指针变量。例如,三级指针int***ppp;
四级指针char****p;[例9.14]
多级指针举例。main(){int*p,i;int**pp;i=54;p=&i;pp=&p;printf("%u\t%u\n",&i,i);printf("%u\t%u\t%u\n",p,*p,&p);printf("%u\t%u\t%u\t%u\n",pp,*pp,**pp,&pp);}654985465498546549665496654985465500pipp&i
6549854&p
65496654986549665500指针数组:数组中的每个元素都为指针型的。用于处理二维数组或多个字符串。定义形式:[存储类型]数据类型*数组名[数组长度说明];注:(1)static和extern型指针数组才可初始化;
(2)不能用自动型变量的地址去初始化static型指针数组。例int*p[6];/*长度为6的指针数组*/
[例9.15]指针数组举例。main(){staticinta[5]={2,4,6,8,9};staticint*num[]={&a[0],&a[1],&a[2],&a[3],&a[4]};int**p,i;p=num;for(i=0;i<5;i++){printf("%d\t",**p);p++;}}num[0]num[1]num[2]num[3]num[4]num24689ap24689num[0]&a[0]&a[1]&a[2]&a[3]&a[4][例9.16]按英文字典的字母顺序对多个字符串进行排序。
“JAVA”“FORTRAN”“Pascal”“BASIC”“C”“FoxBASE”“BASIC”“FoxBASE”
“C”“JAVA”“FORTRAN”“Pascal”100020003000400050006000name[0]name[1]name[2]name[3]name[4]name[5]100020003000400050006000400050002000600010003000#include<string.h>main〔〕{staticchar*name[]={“JAVA”,“FORTRAN”,”Pascal”,“BASIC”,”C”,“FoxBASE”};intn=6;char*temp;inti,j;for(i=0;i<n-1;i++){for(j=i+1;j<n;j++)if(strcmp(name[i],name[j])>0){temp=name[i];name[i]=name[j];name[j]=temp;}}for(i=0;i<n;i++)printf(“%s\n”,name[i]);}
ainta[10];9.3.4指针与多维数组多维数组的地址对于一维数组:数组名a表示数组的首地址,即&a[0]。数组名a是地址常量。
a+i是元素a[i]的地址,即&a[i]。
a[i]
*(a+i)aa+1a+2inta[3][4];a[0]a[1]a[2]200020082016200020022008201020162018a[0][0]a[0][1]a[1][0]a[1][1]a[2][0]a[2][1]a[0][2]a[0][3]a[1][2]a[1][3]a[2][2]a[2][3]行指针与列指针a[0]+1a[1]+1a[2]+1*(a+0)+1*(a+1)+1*(a+2)+1对于二维数组:
a是数组名,包含三个元素a[0],a[1],a[2]。每个元素a[i]又是一个一维数组,包含4个元素。a+i=&a[i]=*(a+i)=a[i]=&a[i][0],值相等,含义不同a+i&a[i],表示第i行首地址,指向行*(a+i)a[i]&a[i][0],表示第i行第0列元素地址,指向列*行指针列指针(第0列〕a[i]+j*(a+i)+j-----第i行第j列的元素地址*(a[i]+j)*(*(a+i)+j)a[i][j](*(a+i))[j]inta[3][4];a[0]a[1]a[2]200020082016200020022008201020162018a[0][0]a[0][1]a[1][0]a[1][1]a[2][0]a[2][1]a[0][2]a[0][3]a[1][2]a[1][3]a[2][2]a[2][3]aa+1a+2注意:二维数组名是二级指针,它见到2个*或[]或其和为2,才是数组元素。2024/3/13《C语言程序设计》-第九章57inta[3][4];a[0][0]a[0][1]a[1][0]a[1][1]a[2][0]a[2][1]a[0][2]a[0][3]a[1][2]a[1][3]a[2][2]a[2][3]二维数组元素表示形式:〔1〕a[1][2]〔2〕*(a[1]+2)〔3〕*(*(a+1)+2)地址表示:(1)a+1
(2)&a[1][0](3)a[1](4)*(a+1)行指针列指针地址表示:(1)&a[1][2](2)a[1]+2(3)*(a+1)+2表示形式含义地址a二维数组名,数组首地址a[0],*(a+0),*a第0行第0列元素地址a+1第1行首地址a[1],*(a+1)第1行第0列元素地址a[1]+2,*(a+1)+2,&a[1][2]第1行第2列元素地址*(a[1]+2),*(*(a+1)+2),a[1][2]第1行第2列元素值20002000200820082012132024/3/13《C语言程序设计》-第九章59复习与思考201、多级指针。
inti=5,*p1=&i,**p2=&p1;2、指针数组。
char*t[5];3、二维数组的行指针和列指针。
inta[4][5];
行指针:a+i
列指针:a[i]
多维数组的指针〔1〕指向多维数组元素的指针变量[例9.18]用指针访问多维数组元素。
inta[3][3]={{1,2,3},{4,5,6},{7,8,9}};int*pa[3]={a[0],a[1],a[2]};int*p=a[0];main(){inti;for(i=0;i<3;i++)printf("%d\t%d\t%d\n",a[i][2-i],*a[i],*(*(a+i)+i));for(i=0;i<3;i++)printf("%d\t%d\n",*pa[i],p[i]);}pa[0]pa[1]
pa[2]a[0]a[1]a[2]147258369311545779114273思考:pa[1][2]的值?〔2〕指向由m个元素组成的一维数组的指针变量
定义形式:
类型标识符(*指针变量名)[m];如:int(*p)[4];比较:①inta[4];〔a有4个元素,每个元素为整型〕②int(*p)[4];这种形式表示*p有4个元素,每个元素为整型。也就是p所指的对象是有4个整型元素的数组,即p是行指针。p(*p)[0](*p)[1](*p)[2](*p)[3][例9.18]输出二维数组任一行任一列元素的值。main〔〕{inta[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}};int(*p)[4],i,j;p=a;/*p得到的是行地址*/scanf(“i=%d,j=%d”,&i,&j);pritnf(a[%d][%d]=%d\n”,i,j,*(*(p+i)+j));}思考:其它三种用p表示a数组元素的形式?9.4指针与函数9.4.4命令行参数9.4.3指向函数的指针9.4.2函数的返回值为指针9.4.1函数参数为指针main(){intx,y;scanf("%d,%d",&x,&y);if(x<y)swap(x,y);printf("\n%d\t%d\n",x,y);}swap(intx1,inty1){intt;t=x1;x1=y1;y1=t;}[例9.20]将输入的数从大到小输出〔普通参数〕函数参数为指针值传递但输出并没有到达目的!1.指针做函数参数main(){intx,y;int*p1,*p2;scanf("%d,%d",&x,&y);
p1=&x;p2=&y;if(x<y)swap(p1,p2);printf("\n%d\t%d\n",x,y);}swap(px,py)int*px,*py;{inttemp;temp=*px;*px=*py;*py=temp;}[例9.20]将输入的数从大到小输出〔指针参数〕地址传递2024/3/13《C语言程序设计》-第九章67结论:主调函数中变量的值假设想通过调用子函数使其改变,要有三个条件:1传变量的地址2对形参指针变量取*操作3做赋值(=)运算while(*t++=*s++)i++;[例9.21]将字符串s复制到t中,并返回被复制的字符个数。intstrcopy(s,t)char*s,*t;{inti=0;while((*t=*s)!='\0'){s++;t++;i++;}return(i);}main(){intn;char*ss=“abcd”,tt[20];n=strcopy(ss,tt);printf("%d,%s",n,tt);}指针能保存函数执行时的某种结果,可与return一起构成多个值返回。2.函数返回多个值指针函数的定义形式:数据类型*函数名〔形参表〕{函数体}9.4.2函数的返回值为指针[例9.22]在一个字符数组中查找一个给定的字符,如果找到那么输出该字符开始的字符串,否那么输出“NOFOUNDTHISCHARACTER”。#include"stdio.h"main(){chars[80],ch,*p,*match();gets(s);ch=getchar();p=match(ch,s);if(p)printf("thereisthestring:%s\n",p);elseprintf("NOFOUNDTHISCHARACTER\n");}char*match(c,s)charc,*s;{intcount=0;while(c!=s[count]&&s[count]!='\0')count++;if(c==s[count])return(&s[count]);return(0);}输入:wertypooypiy输出:thereisthestring:ypooypi函数的指针:就是该函数在内存区域的首地址,以函数名来表示。指向函数的指针:把一个函数名赋给一个指针变量时,该指针变量就称为指向函数的指针。定义形式:数据类型(*函数指针名)();int(*f3)();
//表示f3为指向函数的指针变量,该函数返回一个整型量。int*f3();
//表示f3()函数返回值为指向int的指针。
9.4.3指向函数的指针说明:1.函数的调用可以通过函数名调用,也可以通过函数指针调用〔即用指向函数的指针变量调用〕。2.用函数指针变量p调用函数时,只需用〔*p〕代替函数名即可p=max;(max是函数名)c=(*p)(a,b);等价于c=max(a,b);3.对指向函数的指针变量,象p+n、p++、p--等运算是无意义的。[例9.23]函数在函数间的传递。
#include"stdio.h"#include"string.h"main(){intstrcmp();chars1[80],s2[80];int(*p)();p=strcmp;gets(s1);gets(s2);check(s1,s2,p);}
check(a,b,cmp)char*a,*b;int(*cmp)();{printf("testingforequality\n");if(!(*cmp)(a,b))printf("equal\n");elseprintf("notequal\n");}输入:tyuuiuihfdg输出:testingforequalitynotequal
#include"stdio.h"#include"string.h"#include"stdlib.h"#include"ctype.h"main(){intstrcmp(),numcmp();chars1[80],s2[80];printf("pleaseinput2strings\n");gets(s1);gets(s2);if(isalpha(*s1))check(s1,s2,strcmp);elsecheck(s1,s2,numcmp);}
numcmp(a,b)char*a,*b;{if(atoi(a)==atoi(b))return(0);elsereturn(1);}check(a,b,cmp)char*a,*b;int(*cmp)();{printf("testingforequality\n");if(!(*cmp)(a,b))printf("equal\n");elseprintf("notequal\n");}输入:456输出:testingforequality456equal[例9.24]检查输入数字或字符串的相等性。加例:用函数指针变量作参数,求最大值、最小值和两数之和。voidmain(){inta,b;voidprocess(int,int,int(*fun)();scanf("%d,%d",&a,&b);process(a,b,max);process(a,b,min);process(a,b,add);}voidprocess(intx,inty,int(*fun)()){intresult;result=(*fun)(x,y);printf("%d\n",result);}max(intx,inty){printf(“max=”);return(x>y?x:y);}min(intx,inty){printf(“min=”);return(x<y?x:y);}add(intx,inty){printf(“sum=”);return(x+y);}命令行:在操作系统状态下,为了实现某种工作而键入的一行字符。一般形式:命令名参数1参数2………参数nC:\>compfile1file29.4.4命令行参数有3个字符串的命令行9.4.4命令行参数main(argc,argv)intargc;char*argv[];{………}带参数的main函数形式:其元素指向命令行参数中各字符串形参名任意argv[0]argv[1]argv[2]char*argv[]“file2”“comp”“file1”argvargc=3命令行中参数个数9.4.4命令行参数命令行参数传递命令行实参main(形参)系统自动调用main函数时传递[例9.25]在程序中输出命令行参数的内容。/*tang.c*/main(argc,argv)intargc;char*argv[];{inti;printf("argc=%d\n",argc);printf("commandname:%s\n",argv[0]);for(i=1;i<argc;i++)printf("Argument%d:%s\n",i,argv[i]);}(1)编译、链接tang.c,生成可执行文件tang.exe(2)在DOS状态下运行(tang.exe所在路径下〕例:d:\TC>tang[.exe]dddhopeargc=3Commandname:d:\TC\tang.EXEArgument1:dddArgument2:hopeargv[0]argv[1]argv[2]char*argv[]“hope”“tang”“ddd”argvargc=3思考:拷贝命令copy该如何编写?【例9.26】
用命令行参数带入两个整数及运算符,根据运算符计算结果。#include"stdio.h"main(intargc,char*argv[]){intx,y,result;if(argc!=4)printf("Usage:ERROR!\n");else{x=atoi(argv[2]);y=atoi(argv[3]);switch(argv[1][0]){case′+′:result=x+y;break;case′-′:result=x-y;break;case′*′:result=x*y;break;
case′/′:if(!y){printf("Divideoverflow!\n");exit(0);}result=x/y;break;default:printf("Operattypeerror!\n");result=0;break;}printf("%d%c%d=%d\n",x,*argv[1],y,result);}}假假设本程序的文件名为e723.c,经编译连接后得到的可执行文件名为e723.exe,那么在操作命令工作方式下,可以输入以下命令行:C>e723*34运行结果:3*4=12如键入:C>e723/560那么输出:Divideoverflow!程序的执行方式:可执行文件名操作符数值1数值2在本例中,可执行文件名为e723.exe。9.5.1结构体指针与指向结构体数组的指针9.5指针与结构体9.5.2结构体指针与函数结构体指针(指向结构体的指针):即指向结构体变量的指针变量。用于保存结构体存储空间的首地址。结构体指针的定义
struct
结构体名
*结构体指针变量名;
9.5.1结构体指针与指向结构体数组的指针2024/3/13《C语言程序设计》-第九章83structstudent{lontintnum;charname[20];charsex;}st,d[3];structstudent*p1,*p2;p1=&st;p2=&d[0];P1为指向结构体变量的指针。P2为指向结构体数组的指针。结构体指针变量可以加减1,跳过它所指的结构体类型的长度;结构体指针变量可以做函数的参数或返回值;指向相同结构体类型的指针变量可以组成一个数组,即结构体指针数组。结构体成员的访问有三种方式:结构体变量名.成员名(*结构体指针变量名).成员名结构体指针变量名->成员名
结构体指针的使用structstudent{intnum;charname[20];charsex;}st[]={2001,"LiMing",'M',2002,"Wangfang",'F',2003,"ZhangRong",'M'};main(){inti;structstudent*p;p=&st[0];for(i=0;i<3;i++,p++)printf("%d,%s,%c\n",p->num,(*p).name,st[i].sex);}[例9.27]使用结构体指针访问结构体的成员。2001,LiMing,M2002,Wangfang,F2003,ZhangRong,M注意以下操作的含义:p->num++++p->num(++p)->num2024/3/13《C语言程序设计》-第九章86函数返回值为结构体指针结构体指针做函数的参数9.5.2结构体指针与函数结构体指针作函数的参数[例9.28]
structs{inti;charc;}st={125,'A'};main(){printf("Theolddata:\n");printf("\ti=%d\tc=%c\n",st.i,st.c);sub(&st);printf("Thenewdata:\n");printf("\ti=%d\tc=%c\n",st.i,st.c);}sub(sa)structs*sa;{(*sa).i=2;(*sa).c=(*sa).c+1;}输入:Theolddata:i=125c=A输出:Thenewdata:i=2c=B函数返回值为结构体指针定义形式:struct结构体名*函数名〔形参及说明表〕{函数体}#include“stdlib.h”structs{inti;charc;}*sp;main(){structs*sub();sp=sub();printf("Thedata:\n");printf("i=%d\tc=%c\n",sp->i,(*sp).c);}structs*sub(){char*malloc();structs*sv;sv=(structs*)malloc(sizeof(structs));sv->i=5;sv->c='B';return(sv);}Thedata:i=5c=B【例9.29】函数返回指向结构体的指针
9.6链表链表和动态存储分配用包含指针项的结构体变量构成结点用于动态存储分配的函数链表应用举例
链表是一种数据结构,而且是一种动态数据结构。动态数据结构是在程序运行时,根据需要随机地为某种数据结构分配它们所需的内存间,并且在使用之后释放这些内存空间。从而为有效地利用有限的内存空间提供了有利的手段。链表和动态存储分配所谓链表是指假设干个数据〔每一个数据称为一个“结点”〕按一定的原那么连接起来。这个原那么是:前一个结点“指向”下一个结点,只有通过前一结点才能找到下一个结点。链表有一个“头指针”变量,图中以head表示,它存放一个地址。该地址指向一个元素。链表中每一个元素称为“结点”,每个结点都应包括两个局部:一为用户需要用的实际数据,二为下一个结点的地址。head……NULL链表结点数据区指针区链表头可以看到,这种链表的数据结构,必须利用指针变量才能实现。即:一个结点中应包含一个指针变量,用它存放下一结点的地址。例如,可以设计这样一个结构体类型:
struct
student
{int
num;
float
score;
struct
student*next;
};1malloc()函数(1)格式:malloc(size)(2)功能:开辟一个长度为size个字节的连续存储空间,如果分配成功,那么函数返回值是一个void(或char)型指针,它的值是该分配域的首地址,假设不成功,那么返回NULL。2free()函数(1)格式:free(p)(2)功能:释放由p指向的内存区,p是最近一次调用malloc()函数时返回的值。与链表相关的两个函数2024/3/13《C语言程序设计》-第九章98malloc函数的简单用法inti;int*p;p=&i;scanf(“%d”,p);int*p;p=〔int*〕malloc(2);scanf(“%d”,p);free(p);inti;inta[10];int*p;p=a;for(i=0;i<10;i++)scanf(“%d”,p++);inti;int*p;p=〔int*〕malloc(20);for(i=0;i<10;i++)scanf(“%d”,p+i);free(p);[例9.29]建立一条链表,数据从键盘读取,链表的首结点由head返回。structnode*creat(){structnode*p,*head;char*malloc();inti;head=NULL;for(i=0;i<5;i++){p=(structnode*)malloc(sizeof(*p));if(p==NULL){printf("Memoryistoosmall!\n");exit(0);}scanf("%d",&p->data);p->next=NULL;if(head==NULL)head=p;else{p->next=head;head=p;}}return(head);}#defineNULL0structnode{intdata;structnode*next;};main(){structnode*Head,*np;Head=creat();if(Head==NULL)printf("Creatlinkerror!\n");elsefor(np=Head;np!=NULL;np=np->next)printf("%d\t",np->data);}输入:12345输出:54321图11.19链表应用举例【例9.30】用链表存放学生数据。用结构体数组来存放学生数据是静态存储方法,浪费内存空间。现在我们改用链表来处理,每一结点中存放一个学生的数据。程序由三个函数组成,new_record函数用来新增加一个结点,listall函数用来打印输出已有的全部结点中的数据。程序开始运行时假设键入“E”或“e”那么表示要进行增加新结点的操作,假设键入“L”,或“l”,表示要输出所有结点中数据。#include〞stdlib.h〞main(){charch;intflag=1;head=NULL;while(flag){printf(〞\ntypeˊEˊorˊeˊtoenternewrecord,〞);ch=getchar();switch(ch){caseˊeˊ:caseˊEˊ:new_record();break;caseˊlˊ:caseˊLˊ:listall();break;default:flag=0;}/*endswitch*/}/*endwhile*/
}/*endmain*/structstud{charname[20];longname;intage;charsex;floatscore;structstud*next;};structstud*head,*this,*new;voidnew_record(void){charnumstr[20];new=(structstud*)malloc(sizeof(structstud));/*开辟新结点/*if(head==NUL
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 基于机器学习的自动驾驶系统研究与应用报告
- 护理质量与护理质量监督
- 听力检测的社会意义
- 护理专业的糖尿病护理
- 护理服务沟通技巧与案例分析
- 2025年量子通信安全事件应急预案演练
- 基于数据分析的配件市场报告
- 基于区块链的供应链管理可行性研究
- 旅游公司企业文化建设与传播岗位的面试技巧与要点
- 快消品企业行政主管面试问题
- 个人欠薪协议书范本
- 彩钢瓦遮雨棚安装施工方案
- 信息技术基础 课件 单元1 Windows10 操作系统基础
- 新编护理三基复习测试题
- 社会体育指导员合作协议
- GB 4234.2-2024外科植入物金属材料第2部分:纯钛
- 眼袋手术课件
- 计算机二级WPS考试题及答案
- 手部卫生要讲究学会洗手剪指甲一年级综合实践活动课件
- DL-T5024-2020电力工程地基处理技术规程
- DZ∕T 0153-2014 物化探工程测量规范(正式版)
评论
0/150
提交评论