本课重要知识点:
1.知识点:用typedef定义类型
l 功能:为已有数据类型取别名
l 类型定义形式: typedef 旧类型名 新类型名;(例如:typedef double D ; )
注意:
(1) 定义的新名只是原名的一个别名,并不是建立一个新的数据类型;
(2) 用新名和原名定义的对象具有相同的性质和效果。
例1:(2010-09-39)若有以下语句
typedef struct S
{int g; charh;}T;
以下叙述中正确的是 ( B )
A)可用S定义结构体变量
B)可用T定义结构体变量
C)S是struct类型的变量
D)T是struct S类型的变量
【解析】此题中用typedef 说明的新类型名T,与中间部分的结构体类型具有相同的性质和效果
3. 知识点:结构体变量的定义
具体形式 | 实例 | 说明 | |
---|---|---|---|
形式1 | struct 结构体名{类型标识符 成员名;类型标识符 成员名; …………….};struct 结构体名变量名表列; | struct student{ char num[20];char name[20]; char sex;float score[4];};struct student stu1,stu2; | 特点:先定义类型,后定义变量注意:定义变量时,必须以struct student 开头,缺一不可 |
形式2 | struct 结构体名{ 类型标识符 成员名; 类型标识符 成员名; …………….}变量名表列; | struct student{ char num[20];char name[20]; char sex;float score[4];} stu1,stu2; | 特点:定义类型的同时定义变量注意:之后再定义同类型变量时,也必须必须以struct student 开头 |
形式3 | struct {类型标识符 成员名;类型标识符 成员名; …………….}变量名表列; | struct { char num[20];char name[20]; char sex;float score[4];} stu1,stu2; | 特点:定义类型的同时定义变量注意:此形式省略了结构体名,预示着后续程序中将不再定义该类型变量 |
形式4 | typedef struct 结构体名{ 类型标识符 成员名; 类型标识符 成员名; …………….} STU;STU 变量名表列; | typedef struct student{ char num[20];char name[20]; char sex;float score[4];} STU;STU stu1,stu2; | 特点:先定义类型,后定义变量注意:用STU或struct student定义变量具有同等效果,用STU形式简洁方便 |
例1:(:2009-09-36)下面结构体的定义语句中,错误的是( B )
A)structord{intx;inty;intz;}; structorda;
B)structord{intx;inty;intz;} structorda;
C)structord{intx;inty;intz;}n;
D)struct{intx;inty;intz;}a;
【解析】遵循先定义类型,再定义该类型变量的原则,类型定义末尾的分号“;”必不可少
2.知识点:结构体变量各成员的引用
l 引用结构体变量的成员的方法是:结构体变量名.成员名 (例如:stu1.sex)
l 结构体指针变量引用成员的方法是:
形式1:(*指针变量名).成员名 (例如:(*p).num)
形式2:指针变量名->成员名 (例如:p->num)
l 运算符级别,注意:()和->和 . 同级别,均大于*
设有:
structstudent
{char num;
char name[20];
struct date {int year,mon,day} birth;
float score[4];
};
struct student *p,stu1;
p=&stu1;
成员类型 | 成员 | 操作方式 | 说明 |
---|---|---|---|
普通变量 | 例如:引用成员变量num | 直接赋值:stu1.num=201101;间接赋值:p->num=201101输入:scanf(“%d”,& stu1.num);输出:printf(“%d”,stu1.num); | |
数组 | 例如:引用成员数组元素score[0] | 赋值:stu1.score[0]=75;间接赋值:p-> score[0]=75;输入:scanf(“%f”,& stu1. score[0]);输出:printf(“%f”,stu1. score[0]); | |
字符串 | 例如:字符数组成员作为字符串name | 赋值:strcpy(stu1.name,”zhangsan”);间接赋值:strcpy(p->.name,”zhangsan”);输入:scanf(“%s”, stu1.name);输出:printf(“%s”,stu1.name); | %s作为格式控制时,scanf和printf的输入和输出项均为地址 |
结构体嵌套 | 例如:引用内嵌结构体变量birth的成员year | 赋值:stu1.birth.year=1989;间接赋值:p-> birth.year=1989;输入:scanf(“%d”,& stu1. birth.year)输出:printf(“%d”,stu1. birth.year) |
例1:(2009-9-12)设有定义
struct person
{ int ID;char name[12];} p;
请将scanf("%d", );语句补充完整,使其能够为结构体变量p的成员ID正确读入数据。
【解析】此题答案是 &p.ID ,即在成员ID前缀 p. 表示其从属于变量p,操作方式与普通变量和数组没什么不同,只需要在引用时前面标明属于哪个结构体变量。
例2:(2010-03-38)有以下定义和语句
struct workers
{ int num;
char name[20];
char c;
srruct
{int day;int month;int year;} s;
};
struct workers w,*pw;
pw=&w
能给w中year成员赋1980的语句是 ( D )
A)*pw.year=1980; B)w.year=1980;
C)pw->year=1980; D)w.s.year=1980;
【解析】引用w的内嵌结构体变量s的成员year,应逐级递进。具体方法参考前面表格。
例3:(2011-03-36)设有定义:struct {char mark[12];intnum1;double num2;} t1,t2;,若变量均已正确赋初值,则以下语句中错误的是(C)
A)t1=t2; B)t2.num1=t1.num1; C)t2.mark=t1.mark; D)t2.num2=t1.num2;
【解析】结构体以及结构体成员的赋值,需要类型一致,所有选项都满足,但是mark是结构体中的字符数组的数组名,其数组的首地址,是一个指针常量,只能在初始化的时候赋值,故C错误。
例4:(2011-03-37)有以下程序
struct ord
{ int x,y;}dt[2]={1,2,3,4};
main()
{
struct ord *p=dt;
printf("%d,",++(p->x));printf("%d\n",++(p->y));
}程序运行后的输出结果是(D)
A)1,2 B)4,1 C)3,4 D)2,3
【解析】dt是一个结构体类型的数组,其有两个结构体元素,p是结构体类型指针,其指向dt即指向结构体数组的首地址,p->x和p->y分别是结构体数组第一个元素的x成员和y成员的值,++在前则是先自增1再参与运算,所以输出的是1+1=2,和2+1=3,故选D。
例5:(2011-03-38)有以下程序
struct S
{ int a,b;}data[2]={10,100,20,200};
main()
{ structS p=data[1];
printf("%d\n",++(p.a));
}程序运行后的输出结果是(D)
A)10 B)11 C)20 D)21
【解析】结构体变量p赋值为结构体数组第二个元素的值,即p.a=20,p.b=200;所以输出++(p.a)为21,故选D。
3.知识点:结构体变量与函数调用
l 将一个结构体变量的值传递给另一个函数,有3个方法:
(1)用结构体变量的成员作参数。例如,用stu[1].num作实参,将值传递给形参。用法和用普通变量作实参是一样的,属于“单向值传递”方式。应当注意实参与形参的类型应保持一致。
(2)用结构体变量作实参。 对应形参也是同类型结构体变量,也属于“单向值传递”方式。
(3)用指向结构体变量(或数组)的指针作实参,将结构体变量(或数组元素)的地址传给形参。属于“地址传递”方式,应注意在被调用函数中是否对该地址的值有影响。
例1:(2009-09-14)有以下程序运行后的输出结果是 16
typedefstruct
{intnum;doubles;}REC;
voidfun1(RECx)
{x.num=23;x.s=88.5;}
main()
{RECa={16,90.0};
fun1(a);
printf("%d\n",a.num);
}
【解析】main函数中的fun1(a); 是将a的值单向传递给了形参x,相当于赋值给了x,因此x的值的变化不会影响到a
例2:(2009-09-38)有以下程序
structA
{inta;charb[10];doublec;};
structAf(structAt);
main()
{structAa={1001,"ZhangDa",1098.0};
a=f(a);printf("%d,%s,%6.1f\n",a.a,a.b,a.c);
}
structAf(structAt)
{t.a=1002;strcpy(t.b,"ChangRong");t.c=1202.0;returnt;}
程序运行后的输出结果是 ( D )
A)1001,ZhangDa,1098.0
B)1002,ZhangDa,1202.0
C)1001,ChangRong,1098.0
D)1002,ChangRong,1202.0
【解析】注意在f函数中的t.a=1002;strcpy(t.b,"ChangRong");t.c=1202.0; 这三条语句。
4.知识点:链表
l 当一个结构体中有一个或多个成员的基类型就是本结构体类型时,通常把这种结构体称为可以“引用自身的结构体”,也称为“链表结构”
例如:
struct link
{ char ch;
Struct link *p;
}a;
在此,p是一个可以指向struct link类型变量的指针成员,因此,a.p=&a是合法的表达式,由此构成的存储结构如图所示。
l 对链表进行的操作通常有以下四种:
1.建立带有头结点的单向链表
2.顺序访问单向链表各结点数据域的值(即遍历链表)
struct std
{
int data; /*数据域*/
struct std * next; /*指针域*/
};
…建立头结点和数个节点,即建立以下链表
历链表:
p=head;
while(p!=0)
{
printf("%4d",p->data);
p=p->next;
}
}
3.删除单向链表中的某个结点
删除q指向的节点:
p->next=q->next;或者p->next=r;
free(p);
4.向单向链表中插入结点
将r指向的节点插入p、q所指的两个结点之间:
r->next=q; 或者r->next=p->next;
p->next=r;
例1:(2011-09-37)在以下程序
#include<stdio.h>
main()
{struct node{int n;struct node *next;}*p;
struct node x[3]={{2,x+1},{4,x+2},{6,NULL}};
p=x;
printf(“%d,”,p->n);
printf(“%d\n”,p->next->n);
}程序运行后的输出结果是 (B)
A.2,3 B.2,4 C.3,4 D.4,6
【解析】通过赋值语句p=x,即p=&x[0],使p指向了x[0],因此p->n等价于x[0].n,输出2;p->next等价于x[0].next,即x+1或表示为&x[1],p->next->n也可表示为x[1].n,输出4
例1:(2009-03-15)以下程序把三个NODETYPE型的变量链接成一个简单的链表,并在while循环中输出链表结点数据域中的数据,请填空
#include <stdio.h>
struct node
{int data; struct node *next;};
typedef struct node NODETYPE;
main( )
{NODETYPE a,b,c,*h,*p;
a.data=10;b.data=20;c.data=30;h=&a;
b.next=&b;b.next=&c;c.next=’\0’;
p=h;
while(p){printf(“%d”,p->data); p=p->next ;}
}
【解析】while就是用来遍历链表的,为了能遍历每个结点,每执行一次循环,就要使变量p指向下一个结点,所以空白处应填p=p->next
5.知识点:共用体类型定义
l 共用体是一种构造数据类型(遵循先定义类型,再定义该类型变量的原则)
l 用途:使几个不同类型的变量共占一段内存(相互覆盖)
l 与结构体结构体与共用体
1.区别: 存储方式不同,
结构体变量占用的内存单元,是其所有成员占内存单元的总和,而共用体变量是其所有成员中占用空间最大的成员的内存单元
2.联系:类型定义、变量定义、成员引用等操作方式相同,两种类型可相互嵌套
例1.(06-04—41)有以下程序
main()
{union
{char ch [2];
int d;
}s;
s.d=0x4321;
printf(“%x,%x\n”,s.ch[0],s.ch[1]);
} 在16位编译系统上,程序执行后的输出结果是___ A __
A)21,43 B)43,21 C)43,00 D)21,00
【解析】此题考查整形数据在内存中存放形式以及共用体内存分配。对于共用体而言,字符数组ch与整型变量d共用2个字节的存储空问;存储器存储数据原则是:低地址存放低字节,高地址存放高字节;于是0x4321中2l存放在低字节中,43存放在高字节中,故输出时s.ch[0]输出21,s.ch[1]输出43。