结构体属于一种构造类型,它由程序员自己定义,可以包含多个其他类型的数据(并其称为成员变量)。其与数组有着类似的作用,在C语言中,在一个整体由多个数据构成时,我们用数组来表示这个整体。结构体相同,用来表示多个数据构成的整体。但,不同的是,数组只能用来表示相同类型的数据,而结构体却可以表示不同类型的数据。
在我们所遇到的问题中,很难在一个问题案件中保证只存在一种数据类型,通常情况下一组数据往往有很多种不同的数据类型。在这些情况下,使用简单的基本数据类型甚至是数组都是很困难的并且会极其的繁琐。而结构体则可以有效的解决这个问题。本质上来说结构体还是一种数据类型。
例如:
//结构体的一般形式
struct 结构名{
成员列表
};
//结构成员的类型 可以是变量、数组、指针,甚至是其他结构体 ;
再举一个详细的例子——声明一个学生的结构体
//struct:结构体关键字
//Student:结构体标签的名字。
struct Student
{
char* name; //姓名
int num; //学号
int age; //年龄
float score; //成绩
};
//每个成员变量都用自己的声明来描述,以分号结束。
//上面的声明描述了一个包含四个不同类型的成员的结构,但它还没创建一个实际的数据对象。
结构体变量的定义一般有三种方法。
struct Student //声明结构体
{
char* name; //姓名
int num; //学号
int age; //年龄
float score; //成绩
};
struct Student stu1; //定义结构体变量stu1;
struct Student stu2; //定义结构体变量stu2;
struct Student //声明结构体
{
char* name; //姓名
int num; //学号
int age; //年龄
float score; //成绩
}stu1,stu2; //在定义之后跟变量名
struct
{
char* name; //姓名
int num; //学号
int age; //年龄
float score; //成绩
}stu1; //在定义之后跟变量名
/*注意到!!使用第三种方法就不能与前两种方法一样,再去定义其他的结构体变量了*/
变量初始化一般有四个方法:
struct Student
{
int age; //年龄
int number; //学号
}stu1; //声明类型的同时定义变量stu1
struct Student stu2; //定义结构体变量stu2
//初始化:定义变量的同时赋初值。
struct Student stu3 = {age, number};
struct Student{
char name[20]; //学生姓名
int number; //学号
};
struct Student stu1 = {"liming", 320189456289};//初始化
struct Student stu1, stu2; //定义结构体变量
strcpy(stu1.name, "Jack");
stu1.number = 1889456;
//注意:不能直接给数组名赋值,因为数组名是一个常量。如: stu1.name = "Jack"是非法的!
结构体不仅可以记录不同类型的数据,而且结构体可由程序员自行定义,可以用于记录不同类型的数据,并统一为一种数据类型,使得数据结构是“高内聚,低耦合”的,更利于程序的阅读理解和移植,而且结构体的存储方式可以提高CPU对内存的访问速度。
typedef 为C语言的关键字,作用是为一种数据类型定义一个新名字,这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等)。
typedef 本身是一种存储类的关键字,与 auto、extern、static、register 等关键字不能出现在同一个表达式中。
使用 typedef 定义新类型的方法(步骤):在传统的变量声明表达式里,用(新的)类型名替换变量名,然后把关键字 typedef 加在该语句的开头就可以了。
typedf——数据类型——别名
//【第一步】:
int a; //———— 传统变量声明表达式
//【第二步】:
a=10; //———— 给变量赋值
/*----------------等价于----------------*/
typedf int myint //typedef关键字,myint_t就是我们定义的新类型
myint =10;
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。
以下是顺序表最常见的定义,但也要学习到typedf与结构体的结合!
#define N 10
typedef int SLDataType;//定义了别名SLDataType为 int 数据类型
typedef struct SeqList
{
SLDataType array[N]; //定长数组
size_t size; //有效数据个数
}SeqList;
//注意到在结构体前也同样加了一个typedf,继续往下看
原理:使用定长数组存储元素
缺点:给定大小的数组存在不够用或者浪费的情况。
typedef int SLDataType; //类型重命名,后续要存储其它类型时方便更改
typedef struct SeqList
{
SLDataType* a; //指向动态开辟的数组
size_t size; //有效数据个数
size_t capacity; //容量大小
}SeqList;
//注意到在结构体前也同样加了一个typedf,继续往下看
由于顺序表的插入删除操作需要移动大量的元素,影响了运行效率,因此引入了线性表的链式存储——单链表。单链表通过一组任意的存储单元来存储线性表中的数据元素,不需要使用地址连续的存储单元,因此它不要求在逻辑上相邻的两个元素在物理位置上也相邻。
typedef struct LNode{ //定义单链表结点类型
int data; //数据域,可以是别的各种数据类型,本文统一用int类型
struct LNode *next; //指针域
}LNode, *LinkList;
void InitList(LinkList &L){
L = (LNode *)malloc(sizeof(LinkList));
L->next = NULL;
}
之前学顺序表的结构体:是这样的;
typedf struct {
Elemtype *data;
int MaxSize;
int length;
}Seqlist;
到了单链表为何变成了这样的?
typedf struct LNode {
Elemtype data;
struct LNode *next;
}LNode;*LinkList;
struct LNode {
Elemtype data;
struct LNode *next;
};
typedf struct LNode LNode;
typedf struct LNode *LinkList; //定义一个指向struct LNode 的指针
//要表示一个的单链表时,只需要声明一个头指针L,指向单链表的第一个结点。
LNode *L ;//声明指向单链表第一个节点的指针
或者:
LinkLis L;//声明一个指向单链表第一个结点的指针
这里是引用
https://blog.csdn.net/weixin_64609308/article/details/123856927?ops_request_misc=&request_id=&biz_id=102&utm_term=%E7%BB%93%E6%9E%84%E4%BD%93%E7%9A%84%E5%AD%A6%E4%B9%A0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-1-123856927.nonecase&spm=1018.2226.3001.4187
这里是引用https://blog.csdn.net/liitdar/article/details/80069638?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166260532816800186562600%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=166260532816800186562600&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allbaidu_landing_v2~default-2-80069638-null-null.142v47pc_rank_34_2,201v3control_1&utm_term=typedf&spm=1018.2226.3001.4187