版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、程序设计基础(国家级精品课),张长海,程序设计基础(国家级精品课),第七章 指针 第八章 表单数据组织结构体 第九章 再论函数,第七章 指针,指针与变量 指针运算 指针与数组 指针与字符串 指向指针的指针 本章小结,作业: 7.6 7.8 7.9 7.10 7.13 7.16 习题集:P8520 练习: 7.1-7.5 7.7 7.11 7.12 7.14 7.15 7.17,指针是高级程序设计语言中一个重要的概念 正确灵活运用指针 可有效地表示和使用复杂的数据结构 可动态分配内存空间,节省程序运行空间,提高运行效率 不正确理解和使用指针,指针将是程序中最危险的成分,由此带来的后果可能是无法估
2、量的。,必须清楚:数据在内存中的存储和访问方式 已知:每个变量 在计算机内存占用一块存储区 该存储区的地址就是相应变量的地址 变量可能有值 该存储区保存的内容就是相应变量的值,变量地址,变量名,变量值,变量的存储区,7.1 指针与变量,例如有变量声明 char c=S; int v=27,u=32; int *p = 则编译程序分别给变量 c 、v 、u 、p 分配存储空间如图所示,变量c被分配在B7FF开始的一个字节的内存区域中。B7FF是该存储区域的地址,同时也是变量c的地址,也称B7FF是变量c的指针;该内存区域中存储的字符S是该存储区域的内容,也是变量c的值。,变量v被分配在B800开
3、始的两个字节的内存区域中。B800是该两个字节的存储区域的首地址,同时也是变量v的地址,也称B800是变量v的指针;该内存区域中存储的整数27是该存储区域的内容,也是变量v的值。,变量p被分配在B804开始的四个字节的内存区域中。B804是其首地址,同时也是变量p的地址,也称B804是变量p的指针;该区域中存储的B800是是变量p的值。p是指向int类型变量的指针类型变量,目前它指向变量v ,所以变量p的值是v的地址,也就是B800 ,称p指向v 。,必须理解清楚: 给变量分配的内存区域 该内存区域的地址 该内存区域保存的内容 以及它们之间的关系 一个变量v的指针或称指向变量v的指针 就是给它
4、分配的内存区域的地址 或说是给它分配的内存区域的地址首地址,访问变量 直接访问:直接使用变量v的名字 v*10:用变量v的值(27)乘以10,得270 间接访问:使用指向相应变量的指针 访问变量 v 可以用下面方式来实现: *p (*p)*10 :通过指向 v 的指针变量 p ,采用间接访问的方式实现对变量 v 的访问,取出变量 v 的值参与运算。同样得到值270 。,地址与指针是同意语。变量的指针就是变量的地址,存放变量地址(指针)的变量是指针变量,7.1.1 指针类型与指针变量,指针类型和基类型: 在C中,任何一个类型都伴随着一个指向本类型变量的指针类型 表现形式 设有类型T,则指向T类型
5、变量的指针类型用: T * 表示,T称为该指针类型的基类型。,指针变量:,意义 指针变量简称指针 是一种特殊的变量 它里面存储的“值”被解释成为一个变量的地址,确切的说是计算机内存的一个地址。 声明指针变量 说明指向T类型变量的指针变量使用形式: T*p , *p , *p ; 其中,每个p都是标识符,是被说明的指针类型的变量,确切的说是“指向T类型变量的指针变量”。,指针所指向的类型可以是 基本数据类型 构造型数据类型 指针类型 函数 经常简称 “指向T类型变量的指针变量v” “v指向T类型” “T类型的指针v” 例如 int *iptr1, *iptr2 ; /* 说明指向int类型变量的
6、指针变量 iptr1和iptr2 */ char * cptr ; / 说明指向char类型变量的指针变cptr int x , y ; char ch = a;,指针变量的值是内存地址(宏观上讲是变量的地址) 求取不同类型变量或常量地址的表达方式不同: 基本类型变量、数组成员、结构体变量、公用体变量等,用求地址运算符“ char * cptr; int x , y ; char ch = a; 在此基础上,有操作:,iptr1 = ,cptr = ,x = 5;,iptr2 = ,y = 8;,内存单元,地址,变量,E990,指针iptr1,E994,指针iptr2,E998,指针cptr,
7、E99C,int型变量 x,E99E,int型变量 y,E9A0,char型变量 ch,E99C,E99E,E9A0,a,5,8,如果再执行 iptr1=iptr2;,E99E,7.1.2 指针所指变量,指针变量和指针所指变量是两个不同的概念 指针变量即指针,它本身存储某个内存地址(某个变量的地址)。 指针所指变量为指针变量中所保存的内存地址对应的变量。,程序片段 int * iptr; int i=3 ,j ; iptr = ,运算符“ * ”访问指针所指变量的内容,称为间接引用 运算符。语句: j = *iptr 将把iptr所指内存单元(EAB4)中的内容送入变量j ,此时j的值为3。
8、*iptr表示指针变量iptr所指变量的内容。,3,void main() /* 2 */ int i,j; /* 3 */ int *pmax,*pmin,*p; /* 4 */ printf(Input an integer:); /* 5 */ scanf(%d, /* 16 */ /* 17 */,例7-1 用指针变量实现:输入两个 整数,按从大到小顺序输出,运行结果演示,假设输入25 、38 ,该程序运行到第10行结束时,当程序执行完第13行 pmax=pmin;,当程序执行完第14行 pmin=p;,注意符号“*”的用法: “*” 放在表达式中的指针变量之前 “对指针所指变量的访问
9、”,称为间接引用操作符。 例7-1第17行打印语句中的“*pi”, “*pj”, “*pch”。 “*” 放在指针定义中时,表示指针类型, 指针定义符,用来说明指针变量。 例7-1第5行的“int *pi,*pj;”,说明指向int类型的指针变量pi 、pj ; 第6行的“char *pch ;”,说明指向char类型的指针变量pch 。,7.1.3 空指针与无效指针,NULL是C指针类型的一个特殊值,称为“空” 表示指针变量的值为空,不指向任何变量或函数。 NULL值属于所有指针类型。判断指针变量iptr的值是否为空可以使用 iptr != NULL 或 iptr = NULL 保证指针在没
10、有指向有效对象时取值为NULL是一种良好的编程风格。,有时可能不小心生成无效指针 invalid pointer 无效指针是指一个指针变量无值,它既没有指向确定的变量或函数,也不是NULL。 程序中存在无效指针,不是好的程序设计风格 产生无效指针的原因很多,例如 说明指针变量后还没有给它赋值; 把整型变量转换成指针; 回收为指针所指对象分配存储空间; 指针运算超出数组范围。,例7-2 分析下述程序片段的执行结果,int *p , *q , u , v ; q = , px= /* 将地址4800赋给px, 而不是整数类型4800 */,加 +(+) 如果指针值指向数组的一个成分,C允许对相应指
11、针值加上一个整数表达式。 设指针p指向数组变量a的一个成分 把指针p与一个整数k相加,得到的结果值仍然是个指针值; 该值指向的是“数组a从p原来所指成分开始,向数组尾部移动k个成分后的成分”。,例如: int *p ,*q ,*r ,a100; p= 则 p+3 指向的实际地址是 p= 则 p-3 指向的实际地址是 p= 则 p-q得-5 ; 而 q-p得5 。,判等运算和关系运算 C中可以针对兼容类型的指针进行判等运算和关系运算,得到的结果是bool类型。 包括: 判断两个指针值是否相等或不相等 =、!=; 比较两个指针值的大小关系 、= 、 、= 例子 pxpy 判断px所指向的存储单元地
12、址是否小 于py所指向的存储单元地址。 px=py 判断px与py是否指向同一个存储单元 px=0、px!=0、px=NULL、px!=NULL 都是判断px是否为空指针。,一定要注意,参与关系运算的指针值是否是兼容类型的,如果p指向一个int类型变量,而q指向一个 float 类型变量,进行p与q的比较是错误的。,例7.3 输入一个字符串,求其长度。,#include void main( ) char str255 , *p; int v ; scanf(%s,str); p=str; while( *p!=0 ) p+ ; printf(The string length is %d n
13、; p-str); ,程序运行若输入: abcdef 则输出结果为 The string length is 6,运行结果演示,7.3 指针与数组,密切的关系 数组名是数组的首地址,即a0的地址; 指针值也是一个地址如果一个指针p指向数组a的首地址即指向a0,则p与a表示的是同一个对象。 事实上,在C中把指针和数组当作同一个概念看待,数组名是指针,指针也是数组。 可以认为数组名是常量指针。,7.3.1 用指针标识数组,例如 int a5; int *iptr iptr=a; / 也可以使用 iptr= int i , *p; for(i=0;i5;i+ ) printf(a%d= ,i); s
14、canf ( %d, ,假设分别输入 1、2、3、4、5 在输出阶段: 执行第一个for语句输出结果: 执行第二个for语句输出结果: 执行第三个for语句输出结果:,a0= 1 a1= 2 a2= 3 a3= 4 a4= 5 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5,运行结果演示,7.3.2 指针数组,一维指针数组的声明形式是 T *pn 其中 T 是类型 p 是标识符,是被声明的数组变量 n 是数组尺寸,因运算符 “*” 的优先级低于运算符 “ ” 所以该声明相当于声明 T *(pn) 按此格式,“pn”表示p是n个元素的数组,数组元素是“T *”类型,即指向T类型变量的
15、指针类型。所以p是n个元素的指针数组,数组成分是指向T类型变量的指针。也可以认为p本身是一个指针常量,指向n个元素的指针数组。这个声明形式,声明了一个指针数组p ,如图所示。,指针数组没什么特殊的,是由指针构成的数组。数组中每个元素都是指针。下例定义了指针数组p ,p 包含5个元素,其中每个元素都是int型指针。 int * p5;,例7.5 指向指针的指针、指针数组与数组的关系 void main( ) int a5=23,24,25,26,27; int * n5 ,i ; int *p=n; for( i=0; i5; i+) ni= i+,p+) printf(“%4d”,*p); 程
16、序运行结果将输出: 23 24 25 26 27,“指向指针的指针变量p” “指针数组n”与“数组a” 关系图,运行结果演示,例7.6 把若干给定的字符串按字母顺序排序并输出,void sort_string(char *arr_str ,int n); void out_string(char *arr_str ,int n); int str_cmp( char *str1 , char *str2 ); char *name =basic,programming“ ,great wall,language,computer; void main() sort_string(name,5)
17、; out_string(name,5); ,运行结果演示,该程序首先调用sort_string函数对name数组排序;然后调用out_string函数输出name。 程序声明部分产生如下图的数据结构:,经过sort_string排序后数据结构如下,运行结束产生如下输出: basic computer great wall language programming,常量字符串保存在内存的常量区,void sort_string(char *arr_str,int n) char *temp; int i,j,k; for ( i=0; i 0 ) k=j; temp= arr_stri; ar
18、r_stri= arr_strk; arr_strk=temp; ,void out_string(char *arr_str,int n) int j; for ( j=0;jn;j+) printf( %sn , arr_strj ); ,本程序没有使用标准函数比较两字符串大小,自编函数 int str_cmp( char *str1 , char *str2 ) do if ( *str1 *str2 ) / 比较当前字符 return 1; else if ( *str1 *str2 ) return -1; while ( *(str1+)!=0/ str2长 ,7.4 指针与字符串
19、,字符串实质上是常量字符数组,同时还可以使用字符数组变量保存字符串。 指针与数组有着密切的关系,数组名是指针,指针也可以指向数组。 显然指针与字符串有着密切的关系。 在C中,除了用字符数组保存并标识字符串外,还可以使用字符类型指针指向一个字符串, 从而使用指针访问它所指的字符串。该字符串既可能是字符数组,也可能是字符串常量。,char *sp = “I love china”,*sv; char string = “I am a student”; 定义两个字符指针变量sp 、sv 以及一个字符数组变量string; 并对变量作初始化,使sp指向字符串“I love china”, 而stri
20、ng初始化为“I am a student”。 设变量从A000开始分配内存空间,常量从AA00开始分配内存空间,这个声明产生下图的内存分配结果。,编译系统为字符类型指针变量sp、sv分配指针类型空间;为字符串数组string分配字符型空间,并初始化,把字符串“I am a student”保存在相应数组string的内存空间中。 为了保存字符串常量 “I love china” 编译系统在常量区给它开辟存储空间,这块存储空间的结构与字符数组相同;并初始化字符类型指针变量sp,使它指向字符串“I love china”。,字符串“I love china”是常量字符串,只有通过指向它的指针变量
21、才能访问它,它本身没有名字,sp绝对不是它的名字。目前sp指向它,当然也可以用其它指针变量指向它,sp也可以用于其它用途。例如,下述赋值运算 sv = sp; sp = string; 使得sv指向字符串 “I love china” 而sp又去指向另一个字符串 。,使用字符数组sp可以访问相应字符串,也可以参与一切与字符串有关的运算。例 printf(“%sn”,sp); 将打印出 I am a student 而 sp3 *(sp+3) 的值都是字符“m”。,AA00,A008,【例7.7】编函数把给定字符串复制到另一个字符串。 str_copy(char *str1,char *str2
22、)/复制函数 int i;/计数器 for( i=0; *str1!=0; str1+,i+) str2i=*str1; /str2使用数组形式,str1使用指针形式 ,运行结果演示,【例7.8】编函数比较两个给定字符串大小。 int str_cmp( char *str1 , char *str2 ) do if ( *str1 *str2 ) / 比较当前字符 return 1; / str1长或str1当前字母大于str2 else if ( *str1 *str2 ) return -1; / str2长或str1当前字母小于str2 while ( *(str1+)!=0 / 两个串
23、全部结束,长度相同 ,运行结果演示,不论字符串指针还是字符数组,访问整个字符串要十分小心,有些操作是正确的,有些操作是错误的。 举例如下,请从中深刻体会字符串指针和字符数组的各种用法。, char str20=“I am a teacher”; / 正确,初始化数组str char str020 , str20=“I am a teacher”; str0=str; / 错误,给指针常量赋值,数组不能整体赋值 char str20; str=“I am a teacher”; / 错误,给指针常量赋值,数组不能整体赋值 char str20; str =“I am a teacher”; /
24、错误,给指针常量赋值; / “str ”出现在“=”左端,意义不明确。, char *str; str=“I am a teacher”; / 正确,给指针变量赋值,str指向常量字符串 char str20; scanf ( “%s”,str); / 正确,输入字符串 char *str; scanf ( “%s”,str); / 错误,str不指向任何变量,输入字符串无处放, char *str ,str020; str=str0; scanf ( “%s”,str); / 正确,输入字符串数据从str00开始存放 char *str ,str020; str=str0+5; scanf
25、( “%s”,str); / 正确,输入数据将从str05开始存放 char str20= “I am a teacher”; printf ( “%s”,str); / 正确,打印:I am a teacher, char *str=“I am a teacher”; printf ( “%s”, str); / 正确,打印:I am a teacher char *str=“I am a teacher”; str = str+5; printf ( “%s”, str); / 正确,打印:a teacher char *str= “x=%d y=%fn”; printf (str , x
26、 , y ); / 正确,相当于: printf (“x=%d y=%fn” , x , y );,7.5 指向指针的指针,如果一个指针变量指向的变量仍然是一个指针变量,就构成指向指针变量的指针变量,简称指向指针的指针。如图所示,变量 p 指向一个变量,该变量仍然是指针类型的,它指向一个int类型变量。,P的声明形式是: 类型符 *p 如下程序片段构造下图结构。 int *p , *s , v ; p = 其中声明符 “*p” 声明了指向指针变量的指针变量p 。,使用p访问v内容的形式是 *p 这个间接寻址运算的意义是: p 是指针变量,它的值是指向“指向int类型的指针变量” *p 取上述p
27、的内容,得到一个指针值,该指针值“指向int类型变量” *p 即“*(*p)”再取上述“*p”的内容,得到一个int类型的值。,上述给 v 赋值的语句 v = 300 ; 可以使用指针变量s实现,也可以使用指向指针的指针变量p实现,下述三个语句等价。 v = 300; *s = 300; *p = 300;,使用s访问v内容的形式是 *s,指向指针的指针在实际程序中有很大用处,程序的命令行参数使用指向指针的指针。经常使用指针数组实现指向指针的指针。设有程序片段 char c1 =“copy”, c2 =“jilin.dat”; char c3 =changchun.dat , c4 =beij
28、ing ; char *aptr4 , *ptr1 ,*ptr2 ; ptr1 = aptr ; *ptr1 = c1 ; *(ptr1+1) = c2; aptr2 = c3; ptr13 = c4; ptr2 = ,下图描述了上述程序片段产生的结果, 数组aptr是一个指针数组,它的每个元素值是一个指针,指向一个char型变量,数组名aptr是一个指向指针的指针(指针常量); 变量ptr1,ptr2 也是指向指针的指针(指针变量);,如下操作都访问c3的第8个元素,得到字符值“u”。 c37 、 *(c3+7) aptr27 、 ptr127 、 ptr227 *(aptr2+7) 、 *
29、(ptr12+7) 、 *(ptr22+7) (*(aptr+2)7 、 (*(ptr1+2)7 、 (*(ptr2+2)7 *(*(aptr+2)+7) 、 *(*(ptr1+2)+7) 、 *(*(ptr2+2)+7),本章小结,本章主要介绍指针的概念与操作,并对指针与数组关系进行详细介绍。重点掌握 指针变量与指针所指变量之间的关系, 指针与数组之间的关系。 只有掌握好这两种关系才能够正确理解指针概念以及操作,从而正确使用指针。,第八章 表单数据组织结构体,图书卡管理 保存图书卡结构体,作业: 8.3 8.6 8.9 习题集:P1053.a 练习: 8.1 8.2 8.4 8.8 8.11
30、-8.13,8.1 图书卡管理,【例8-6】在某图书管理系统中,图书检索卡结构如图所示:,编程序,从终端输入100张卡片保存起来;然后根据用户不断输入的书号,检索相应书名、作者名、语种、摘要,并输出,直到输入书号的类号为z。,解:由题目要求,显然程序分成两部分:输入、检索输出。输入100张卡片,显然是一个循环,输入一张保存一张;检索也可以采用最简单的顺序检索。整个程序逻辑十分简单。根本不必画出PAD。 问题是用什么数据结构保存卡片,显然应该把每张卡片描述为一个数据,统一处理。问题是每张卡片中包含六个子数据,每个子数据的类型不同,用前边学的数据组织方式显然解决不了问题。 现实世界中有很多这类数据
31、:一个数据项由多个子数据组成,而每个子数据的类型可能不一样。本章介绍一种数据组织方式结构体,使用结构体可以描述这一类由不同类型子数据项组成的数据。另外本章还将讲述与结构体类型密切相关的联合体类型。结构体类型和联合体类型都是构造型数据类型。 用结构体类型描述图书卡片,编出如下程序。,#include stdio.h enum class_language Chinese,English,Japanese,Spaish,Russian ;/语种枚举类型 struct date / 日期结构体类型 int year,month,day ; ; struct bookno / 书号结构体类型 char
32、 catalogue ; int order ; ; struct bookcard / 检索卡结构体类型 char name32,author16; enum class_language languge ; struct date publishingdate ; struct bookno no ; char abstract256; groupcard100 ;,struct bookcard inputcard( void );/输入一张卡片函数原型 void inputbookno(struct bookno * );/ 输入书号函数原型 void searchbook( stru
33、ct bookno );/检索函数原型 void out_answer( struct bookcard * ); /输出结果函数原型 void main()int i ; /* 主程序 */ struct bookno no1; /输入部分 for ( i=0;iL;i+) groupcardi = inputcard( ); /检索部分 printf(nstart search:); inputbookno( /输入欲检索的下一个书号 / 主程序结束,struct bookcard inputcard( void ) int k; /* 输入一张卡片函数 */ struct bookcar
34、d card; printf(nn new card:); printf(nplease input bookname:); scanf(%s, ); printf(nplease input authorname:); scanf(%s, card.author); printf(nplease choose class_language:); printf(n1.Chinese 2.English 3.Japanese 4.Spaish 5.Russian:); scanf(%d, ,printf(nplease input publishing year、month、d
35、ay:); scanf(%d%d%d, ,/输入一个书号函数 void inputbookno(struct bookno * no) printf(nstart search:nplease input bookno.catalogue:); scanf(%c, ,/* 检索函数 */ void searchbook(struct bookno no2) int k; for ( k=0; kL; k+ ) if ( (groupcardk.no.catalogue = no2.catalogue ) ,/* 输出检索结果函数 */ void out_answer( struct bookc
36、ard *card0 ) printf( NAME:%sn, card0-name ); printf( AUTHOR:%sn, card0-author); printf( LANGUGE:%sn, card0-languge ); printf(Publish date:%d.%d.%dn ,card0-publishingdate.year ,card0-publishingdate.month ,card0-publishingdate.day); printf( ABSTRACT:n ) ; printf( %s,card0-abstract) ; printf(n); ,运行结果演
37、示,8.2 保存图书卡结构体 程序例8.1中使用结构体保存成分类型不同的图书卡片数据。 类型struct bookcard有六个不同类型的成分,分别保存图书卡片的六个成分; 类型struct date是struct bookcard类型的成分类型,有三个成分,都是整数类型,分别保存图书卡片中出版日期的年、月、日; 类型struct bookno也是struct bookcard类型的成分类型,有两个不同类型的成分,分别保存图书卡片中书号的类号和序号。,struct bookcard / 检索卡结构体类型 char name32,author16; enum class_language lan
38、guge ; struct date publishingdate ; struct bookno no ; char abstract256; groupcard100 ;,struct date / 日期结构体类型 int year,month,day ; ;,struct bookno / 书号结构体类型 char catalogue ; int order ; ;,与数组一样,结构体也是变量的集合,但其中成分变量有可能类型不同。结构体类型的特点是: 一个数据项由多个子数据项组成,而且每个子数据项的类型可能不一样。,在人事档案管理中,每个人的自然情况表可能包含:名字(字符串型)、年令(整
39、型)、出生时间(三个整型)、性别(枚举)等等。,研究人造卫星,每个人造卫星的信息可能包括:名字(字符型)、发射时间(三个整数)、重量(实型)、直径(实型)、轨道半径(实型)、与赤道夹角(实型)等等。,在程序设计语言中使用结构体描述这一类由不同类型子数据项组成的数据。,8.2.1 定义结构体类型,结构体类型 结构体类型是分量的集合。 分量也称成员、成分、域, 分量类型可以不同。,“结构体类型定义”呈如下两种形式:,struct是保留字,引导一个结构体类型定义,每个 t 是一个类型说明符,可以是任意类型的任何形式的类型说明符。它说明后边诸标识符 id 的类型,每个 id 是一个成员声明符,具体声明
40、结构体类型的一个分量,它最终涉及的标识符是该分量的名字;要求在整个结构体类型定义内,诸 id 中声明的各个分量的名字互不相同;每个id的类型是它前边的t表记的类型。,sid是一个标识符,称结构体标签,起标记该结构体类型作用.,例8-2 一个人的自然情况表例8-3 卫星数据类型,enum sext male , female ; struct date int year ,month ,day ; ; struct preson char name10 ; int age ; enum sext sex ; struct date birthdate ; ;,struct mansatellit
41、e char name10 ; struct date lounchdate ; float weight, diameter, orbitrad, angle ; ;,date是一个结构体类型,包含三个成分 成分year为int类型 成分month为int类型 成分day为int类型,bookno有两个成分,bookcard有六个成分。 其中嵌套两个结构体类型成分: publishingdate、bookno,preson有四个成分, 成分name为数组类型, 成分age为int类型, 成分sex为枚举类型, 成分birthdate仍为一个结构体类型,与其它构造型类型一样,结构体类型也可以嵌
42、套,mansatellite有六个成分,结构体类型引用 在struct后跟以结构体标签,称为“结构体类型引用”。在例11-1的结构体类型定义的意义下: struct date struct preson struct mansatellite 都是结构体类型引用,使用它们将分别标记相应结构体定义。,结构体类型说明符: 结构体类型定义和结构体类型引用统称“结构体类型说明符”。使用结构体类型说明符可以 定义结构体类型的类型名, 还可以声明结构体类型变量。,8.2.2 结构体类型名,与一般类型一样,使用 typedef 可以定义结构体 类型名。形式是: typedef 结构体类型说明符 标识符,例8
43、-4 定义结构体类型名,typedef struct date int year,month,day ; datetype ; typedef char tstring1010; typedef struct tstring10 name ; int age ; enum sext sex ; struct date birthdate ; presontype ; typedef struct mansatellite mansatellitetype,datetype birthdate;,8.2.3 结构体变量,结构体类型变量声明可以采取如下三种形式之一 使用结构体类型引用 直接使用结构
44、体类型定义 使用typedef定义的结构体类型名,例:结构体变量声明,struct preson zhang ; struct date int year,month,day ; dateofbirth; struct char author10 ; datetype publish_date ; int page_number ; programming ; mansatellitetype first_east ;,变量zhang用结构体类型引用声明 是struct preson类型,具有如图结构,变量dateofbirth使用完整的结构体类型定义声明,具有如图结构,变量programmi
45、ng使用不带结构体标签的结构体类型定义声明,包含3个成分,分别为字符数组类型的author、datetype类型的publish_date、int类型的page_number,结构如图所示;,变量first_east使用typedef定义的类型标识符mansatellitetype声明,具有如图结构,类型定义不分配存储空间,只说明一个数据类型的框架结构。只有到变量声明时才给变量分配存储空间,并且使得被声明的变量具有相应类型的结构。 到目前为止本章定义的所有标识符,只有本节声明的四个变量zhang、dateofbirth、programming、first_east具有实体,被分配存储空间。 类
46、型标识符只是定义了一个数据类型的框架,不占用存储空间,只给相应类型起一个名字。,8.2.4 指向结构体变量的指针,任何类型都伴随一个指向相应类型的指针类型,并可以声明相应指针类型的变量,结构体类型当然不例外。,输出检索结果函数out_anser中的card0就是一个指向结构体变量的指针变量。使用形式 struct bookcard *card0 声明;,在例8.1中: 输入一个书号函数 inputbookno中的no也是一个指向结构体变量的指针变量。使用形式 struct bookno * no 声明。,void inputbookno(struct bookno * no) printf(n
47、start search:nplease input bookno.catalogue:); scanf(%c, ,void out_answer( struct bookcard *card0 ) printf( NAME:%sn, card0-name ); printf( AUTHOR:%sn, card0-author); printf( LANGUGE:%sn, card0-languge ); printf(Publish date:%d.%d.%dn ,card0-publishingdate.year ,card0-publishingdate.month ,card0-pub
48、lishingdate.day); printf( ABSTRACT:n ) ; printf( %s,card0-abstract) ; printf(n); ,在前几节声明的基础上,下述例子声明指向不同结构体类型变量的指针变量pointer_preson、dateofpointer、p、p_east。,struct preson *pointer_preson ; struct date int year,month,day ; *dateofpointer ; struct char author10 ; datetype publish_date ; int page_number ;
49、 *p ; mansatellitetype *p_east,例:指向结构体类型变量的指针变量,变量pointer_preson为指向标签为preson的结构体类型变量的指针变量。 pointer_preson可以指向相应结构体类型的变量。比如 pointer_preson = ,变量dateofpointer为指向标签为date的结构体类型变量的指针变量。 dateofpointer可以指向相应结构体类型的变量。比如 dateofpointer = ,变量p为指向无标签结构体类型变量的指针变量。 P 可以指向相应结构体类型的变量。比如 p = ,变量p_east为指向结构体类型mansate
50、llitetype变量的指针变量。 p_east 可以指向相应结构体类型的变量。比如 p_east = ,8.2.5 访问结构体变量的成分,访问结构体变量的一个成分,使用成员选择表达式。包括“直接成员选择”和“间接成员选择”两类,直接成员选择 直接成员选择表达式针对一般的结构体变量。 形式是: r . w r 是结构体变量; w是 r 所属结构体类型中的一个成员名字 下述成员选择表达式是合法的: programming_pascal.author,间接成员选择 间接成员选择表达式针对指向结构体变量的指针变量 形式是 p-w p 是一个指向结构体变量的指针变量; w 是p所
51、指向结构体变量所属类型中的一个成员名字 下述成员选择表达式是合法的: pointer_preson - name p_east - weight p_east - lounchdate,当然也可以首先对指针变量进行求地址运算,然后使用直接成员选择。比如上述三个选择表达式还可以写成如下形式。由于优先级的原因,这里的括号是必须的。 (*pointer_preson).name (*p_east).weight (*p_east).lounchdate,由于成员选择表达式本身也是一个变量访问,它是相应成分类型的一个变量,它与成分类型的其它变量一样,凡是可以使用那些变量的地方都可以使用成员选择表达式。
52、对于嵌套结构体,可以认为“成员选择表达式”仍然是一个“后缀表达式”,所以可以继续应用“成员选择表达式”的规则访问里层的成分。例: zhang.birthdate.mouth p_east - lounchdate.year,例8-5 设计表示复数的结构体类型, 给出复数加法和乘法函数,解: /* 复数类型 */ typedef struct complex float real_part,imaginary_part ; complex_type,/* 复数加法 */ complex_type complex_add(complex_type x, complex_type y) comple
53、x_type add; add.real_part=x.real_part+y.real_part; add.imaginary_part=x.imaginary_part+y.imaginary_part; return add; ,/* 复数乘法 */ complex_type complex_mul ( complex_type x, complex_type y ) complex_type product ; product.real_part = x.real_part * y.real_part + x.imaginary_part * y.imaginaty_part ; pr
54、oduct.imaginary_part = x.real_part * y.imaginary_part + x.imaginaty_part * y.real_part ; return product ; ,运行结果演示,本章小结,本章讲述构造数据类型 结构体类型 结构体变量 结构体成分变量成分选择表达式 枚举类型 重点掌握结构体应用,第九章 再论函数,函数参数 函数值 作用域 局部量和全局量 递归程序设计 本章小结,作业: 9.8 9.11 习题集:P9116 练习: 9.1 9.2 9.3 9.5 9.6 9.9,9.1 参数,9.1.1 传递直线方程系数指针作参数,第五章求三角形重
55、心的例题5.2的程序,传递一个直线方程的两个系数信息时让人感到十分别扭,函数不能把多个计算结果带回调用处,不得不使用全局变量。使用指针参数可以解决这个问题。,float xa,ya,xb,yb,xc,yc; /分别保存三角形三个顶点点的X、Y方向坐标 float xd,yd,xe,ye ; /分别表示中点D、E坐标 float a1,b1,a2,b2,a,b;/分别表示中线AD、BE的方程系数, a、b临时变量 float xo,yo;/重心O的坐标 /* 求中线:参数:三角形三个顶点r、s、t的x、y坐标 */ void lines( float xr,float yr,float xs,f
56、loat ys,float xt,float yt ,float *a,float *b)/6 float xu,yu;/中点u坐标/7 xu=(xs+xt)/2; /求st边的中点u/8 yu=(ys+yt)/2;/9 /求过r、u两点的直线方程/10 *a=(yr-yu)/(xr-xu); /计算系数a;用指针参数带回主程序/11 *b=yr - *a * xr ;/计算系数b;用指针参数带回主程序/12 /13 void main(void) / 主函数/14 / 输入三个点的X、Y方向坐标 346 360 416 108 116 212 printf(please input xa,y
57、a,xb,yb,xc,yc:n);/15 scanf(%f%f%f %f%f%f,/ 打印输出 /24,运行结果演示,函数lines用指针参数a 、b代替了原来的全局量和函数值来传递计算结果。,在函数声明中,增加形式参数a 、b ,并把它声明成指针类型,构成指针参数,在函数调用中,用变量的指针(地址)作实在参数,对应相应形式参数。,在函数声明中,对形式参数a 、b以间接寻址方式赋值,把值直接送入实在参数指针所指向的变量中。,以函数调用lines(xa,ya,xb,yb,xc,yc, temp=*xx; *xx=*yy; *yy=temp; void main() int x,y; scanf(%d %d, ,6,3,y,x,2342,2340,返回值,xx,2346,2344,yy,234A,temp,234E,main,swap,2340,2342,3,6,3,程序输出:6 3,9.1.2 对任意数组排序-数组作参数,第
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 张家口市重点中学2026-2027学年数学七上期末学业质量监测试题含解析
- 陕西省西安市交通大附属中学2027届七年级数学第一学期期末统考试题含解析
- 辽宁省沈阳市和平区2027届六年级数学第一学期期末经典试题含解析
- 内蒙古北京师范大乌海附属学校2026年八年级物理第一学期期末调研模拟试题含解析
- 清远市重点中学2026年数学七上期末监测试题含解析
- 福建省南平市2027届数学六年级第一学期期末复习检测试题含解析
- 山东省枣庄市台儿庄区2026-2027学年数学六年级第一学期期末经典模拟试题含解析
- 陕西省蓝田县联考2026年物理八上期末复习检测试题含解析
- 织造工艺参数调整标准细则
- 麻纺企业安全生产监督细则
- 动物产品检验技术课件
- DB5301∕T 102-2024 应用软件定制开发成本测算指南
- 消毒公司企业管理制度
- 广东东莞公开招聘农村(村务)工作者笔试题含答案2024年
- 电力一把手讲安全
- 实验室危化品应急预案
- 洪涝灾害灾区预防性消毒技术指南
- 手足外科植皮护理查房
- 临床血液学和血液学检验-血象和骨髓象检验课件
- 交通信号灯控制器设计报告
- YY/T 0597-2006施夹钳
评论
0/150
提交评论