第十四章 结构体内容讲解二
- 格式:doc
- 大小:79.50 KB
- 文档页数:8
c语言结构体内容C语言结构体是一种自定义的数据类型,它由多个不同类型的数据组成,可以表示一个实体的多个属性或特征。
结构体在C语言中被广泛应用,它能够提高程序的可读性和可维护性,使程序员能够更好地组织和管理数据。
一、结构体的定义和声明结构体的定义使用关键字struct,后面跟着结构体的标识符和一对花括号,花括号中是结构体的成员变量。
每个成员变量都有自己的数据类型和标识符,用来表示不同的属性。
结构体的声明可以在定义时进行,也可以在定义之后进行。
二、结构体的初始化结构体的初始化可以使用两种方式:一种是使用“{}”初始化器,按照成员变量的顺序给出每个成员变量的值;另一种是使用“.”运算符给成员变量赋值。
结构体的初始化可以在定义时进行,也可以在定义之后进行。
三、结构体的访问结构体的成员变量可以使用“.”运算符进行访问,通过结构体变量名和成员变量名来获取或设置相应的值。
结构体的成员变量也可以通过指针来访问,使用“->”运算符来取代“.”运算符。
四、结构体的使用结构体可以作为函数的参数和返回值,通过传递结构体变量的地址来实现对结构体内容的修改。
结构体也可以作为数组的元素,用来表示复杂的数据结构。
五、结构体的嵌套结构体可以嵌套定义,即在结构体中使用其他结构体作为成员变量,从而构建更复杂的数据类型。
嵌套结构体的访问需要使用多个“.”或“->”运算符。
六、结构体的对齐为了提高内存访问效率,编译器会对结构体进行对齐操作,保证结构体成员变量的地址是对齐的。
对齐规则可以通过编译器的指令或预处理宏来设置,以满足特定的需求。
七、结构体的大小结构体的大小由其成员变量的大小和对齐方式决定,可以通过sizeof运算符来获取结构体的大小。
结构体的大小是成员变量大小的总和,可能会因为对齐而有所增加。
八、结构体的比较结构体变量之间可以进行比较操作,比较的结果是结构体成员变量逐个比较的结果。
对于相同类型的结构体,可以使用memcmp函数进行比较。
c语言结构体知识点总结C语言结构体知识点总结一、什么是结构体结构体是C语言中一种自定义的数据类型,用来将不同类型的数据组合在一起,形成一个新的数据类型。
结构体可以包含不同的数据类型,例如整型、字符型、浮点型等,还可以包含其他的结构体,用来表示更复杂的数据结构。
二、结构体的定义和声明结构体的定义使用关键字struct,后面跟上结构体的名称,然后是一对花括号{},花括号中是结构体的成员变量及其类型。
结构体的声明使用结构体名称和变量名,类似于普通变量的声明。
三、结构体成员的访问结构体成员的访问使用成员访问运算符.,通过结构体变量名加上成员名称来访问结构体成员。
例如,如果有一个名为person的结构体变量,其中有一个成员名为name,可以使用来访问该成员变量。
四、结构体的初始化结构体变量可以通过以下几种方式进行初始化:1. 声明时进行初始化:在结构体变量声明时,使用花括号{}括起来的初始化值列表进行初始化。
2. 使用成员访问运算符逐个初始化:使用结构体变量名加上成员名称,通过等号=赋值的方式逐个初始化结构体成员。
3. 使用typedef定义结构体类型并初始化:通过typedef关键字定义结构体类型,并在初始化时使用该类型进行初始化。
五、结构体数组结构体数组是由多个结构体变量组成的数组。
可以通过定义结构体数组的方式来存储和操作多个结构体对象。
结构体数组的访问方式类似于普通数组,通过下标来访问其中的元素。
六、结构体指针结构体指针是指向结构体变量的指针变量。
可以使用结构体指针访问结构体成员,也可以通过结构体指针来操作结构体变量。
结构体指针的定义和使用与普通指针类似。
七、结构体作为函数参数可以将结构体作为函数的参数,传递结构体变量给函数进行操作。
可以通过传值或传址的方式将结构体传递给函数,并在函数中对结构体进行修改。
八、结构体嵌套结构体可以嵌套定义,即一个结构体中可以包含另一个结构体作为成员变量。
通过结构体嵌套可以构建更复杂的数据结构,提高代码的可读性和可维护性。
结构体定义和使用
1结构体的定义
struct 结构体名
{
成员列表;
}
说明:
(1)struct(数据类型)结构体
比如:inti; i的类型就是整型
(2)成员列表由若干个成员组成,每个成员
都是该结构的一个组成部分。
对每个成员也必
须作类型说明。
2int是C语言自带的结构类型
我也创了一个结构类型jj
inti;i是变量
那么我创的类型的变量怎么设置???
#先定义结构,再说明结构变量。
如:
struct jj
{
intnum;
char name[20];
int age;
};
struct jj boy1,boy2;
说明了两个变量boy1和boy2为jj结构类型。
# 在定义结构类型的同时说明结构变量。
例如:
struct jj
{
intnum;
char name[20];
int age;
}boy1,boy2;
# 直接说明结构变量。
例如:
struct
{
intnum;
char name[20];
int age;
}boy1,boy2;
第三种方法与第二种方法的区别在于第三种方法中省去了结构名,而直接给出结构变量。
说明了boy1,boy2变量为stu类型后,即可向这两个变量中的各个成员赋值。
第十四章结构体、共用体和用户自定义类型当前讲授历年真题有以下程序struct STU{ char name[10]; int num; float TotalScore; };void f(struct STU *p){ struct STU s[2]={{"SunDan",20044,550},{"Penghua",20045,537}}, *q=s;++p ; ++q; *p=*q;}main(){ struct STU s[3]={{"YangSan",20041,703},{"LiSiGuo",20042,580}};f(s);printf("%s %d %3.0f\n", s[1].name, s[1].num, s[1].TotalScore);}程序运行后的输出结果是()。
A.SunDan 20044 550 B.Penghua 20045 537C.LiSiGuo 20042 580 D.SunDan 20041 703【答案】B【解析】此题考查的是结构数组用作函数参数。
在主函数中语句f(s);是用数组名作为函数调用函数f(),数组名是数组首地址,因此,函数f()中的形参结构体指针变量p指向主函数中的数组元素s[0]。
在函数f()中,执行语句++p;将指针p往后移动了一位,所以指针p现在指向主函数中的数组元素s[1];执行语句++p;将指针变量q指向函数f()中的结构数组元素s[1];执行语句*p=*q;将函数f()中数组元素s[1]赋给主函数中的数组元素s[1],故最终输出为: Penghua 20045 537,应该选择B。
7.利用结构体变量构成链表(1)单向链表的概念struct slist{ int data;struct slist *next;};typedef struct slist SLIST;(2)建立带有头结点的单向链表【例】编写函数creat_slistl,建立如上图所示的带有头结点的单向链表。
#include <stdio.h>#include <stdlib.h>SLIST *creat_slist1(){ int c;SLIST *h,*s,*r;h=(SLIST *)malloc(sizeof(SLIST));/*生成头结点*/r=h;/*r指向当前表尾*/scanf(“%d”,&c) /*读入数据*/while(c!=1) /*未读到数据结束标志时进入循环*/ { s=(SLIST *)malloc(sizeof(SLIST));/*生成一个新结点*/s->data=c /*读入的数据存入新结点的data域*/ r->next=s:/*新结点连到表尾*/r=s:/*r指向当前表尾*/scanf(“%d”,&c);/*读入数据*/}r->next=‘\0’;/*置链表结束标志*/return h;/*返回表头指针*/:}main(){ SLIST *head;……head=creat_slistl()……}(3)顺序访问链表中各结点的数据域【例】编写函数print_slist,顺序输出单向链表各结点数据域中的内容。
#include<stdio.h>#include<stdlib.h>void print_slist(SLIST *head){ SLIST *p; .p=head->next;/*p指向头结点后的第一个结点*/ if(p==‘\O’)printf(“Linklist is null!\n”);/*链表为空(只有头结点)*/ else /*链表非空*/{printf(“head”);do{printf(“->%d”,p->data);/*输出当前结点数据域中的值*/p=p->next;/*p指向下一个结点*/}while(p!=‘\O’);/*未到链表尾,继续循环*/printf(“->end\n”);}}(4)单向链表中插入结点【例】编写函数insert_snode,它的功能是:在值为x的结点前插入值为y的结点,若值为x的结点不存在,则插在表尾。
在进行插入操作的过程中,可能遇到三种情况:①链表非空,值为x的结点存在,新结点应插在该结点之前。
②链表非空,但值为x的结点不存在,按要求,新结点插在表尾。
③链表为空表,这种情况相当于值为x的结点不存在,新结点插在表尾,即插在头结点之后,作为表的第一个结点。
#include<stdio.h>#include<stdlib.h>insert_snode(SLIST *head,int x,int y){ SLIST *s,*p,*q;s=(SLIST *)malloc(sizeof(SLIST));/*生成新结点*/。
s->data=y;/*新结点中存入Y值*/q=head;p=head->next;/*p指向第一个结点*/while((p!=‘\O’)&&(p->data!=x)) /*表非空且未到表尾,查找x的位置*/ { q=p;p=p->next;} /*q指向P的前趋结点*/s->next=p;/*图中第①步*/q->next=s;/*图中第②步*//*x存在,插在x之前;x不存在,p的值为NULL,插在表尾*/}注意:while((p!=‘\O’)&&(p->data!=x)) 中的两个条件顺序不能对调!当p==NULL时,C 编译程序将“短路”掉第二个条件,不做判断,否则如果先判断p->data!=x ,由于p中的值已为NULL,这时再要访问p->data,就会发生访问虚地址的错误操作。
(5)删除单向链表中的结点为了删除单向链表中的某个结点,首先要找到待删结点的前趋结点,然后将此前趋结点的指针域去指向待删结点的后续结点,最后释放被删结点所占存储空间。
【例】编写函数delete_snode,它的功能是:删除链表中值为x的结点。
#include<stdio.h>#include<stdlib.h>delete_snode(SLIST *head,int x){ SLIST *p,*q;q=head;p=head->next;/*p指向第一个结点*/while((p!=‘\O’)&&(p->data!=x)) /*表非空且未到表尾,查找x的位置*/{ q=p;p=p->next;} /*q指向P的前趋结点*/q->next=p->next;/*删除p所指结点*/free(p); /*释放p所指结点*/}历年真题1.程序中已构成如下图所示的不带头结点的单向链表结构,指针变量s、p、q均已正确定义,并用于指向链表结点,指针变量s总是作为头指针指向链表的第一个结点。
若有以下程序段q=s; s=s->next; p=s;while(p->next) p=p->next;p->next=q; q->next=NULL;该程序段实现的功能是()。
A.首结点成为尾结点B.尾结点成为首结点C.删除首结点D.删除尾结点隐藏答案【答案】A【解析】因为刚开始时s指向链表首结点,所以语句q=s;使q也指向链表首结点。
s=s->next; p=s;语句使s和p都指向首结点的下一个结点。
接下来是一个while循环,循环条件为p->next,即当p没有指向链表尾时执行循环体p=p->next;让p指向下一个结点,所以当循环结束时,p指向链表尾结点。
然后执行p->next=q;q->next=NULL;使q所指结点(原首结点)成为尾结点,此时s指向首结点。
故应该选择A。
2.有以下结构体说明和变量定义,如下图所示,指针p、q、r分别指向一个链表中的三个连续结点。
struct node{ int data;struct node *next;} *p, *q, *r;现要将q和r所指结点的先后位置交换,同时要保持链表的连续,以下错误的程序段是()。
A.r->next=q; q->next=r->next; p->next=r;B.q->next=r->next; p->next=r; r->next=q;C.p->next=r; q->next=r->next; r->next=q;D.q->next=r->next; r->next=q; p->next=r;隐藏答案【答案】A【解析】选项A的第一步操作:r->next=q;执行结果如下图:执行完这步以后r原来所指结点后面的所有结点与原链表断开,无法保持链表的连续,故选项A是错误的程序段。
选项B的三步操作:第一步,q->next=r->next; 执行结果如下图:第二步,p->next=r; 执行结果如下图:第三步,r->next=q; 执行结果如下图:显然,选项B的三步操作完成了q和r所指结点的先后位置交换,同时保持了链表的连续的任务。
请读者自己通过图解的方法分析选项C和D。
综上,选项A符合题意。
3.以下程序把三个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;a.next=&b;b.next=&c;c.next=’\0’;p=h;while(p){printf(“&d”,p->data);______;}}【答案】p=p->next【解析】本题建立一个简单的链表程序最后的while循环输出链表结点数据域中的数据,while(p)等价于while(p!=NULL),p指针逐步指向结点a、结点b、结点c,最后指向NULL。
所以空应该填p=p->next。
三、共用体用途:使几个不同类型的变量共占一段内存(相互覆盖)。
1.共用体类型的说明和变量定义(1)共用体类型的说明union 共用体标识名{ 类型名1 共用体成员名1;类型名2 共用体成员名2;……类型名n 共用体成员名n;};(2)共用体变量的定义共用体变量的定义和结构体变量的定义相似,也可以采用四种方式说明:①共用体变量在定义的同时只能用第一个成员的类型的值进行初始化,因此,以上定义的变量s1和s2,在定义的同时只能赋予整型值。