c语言结构体
一.定义结构体
一般采用
1.第一种
struct 结构体名
{
成员表列
}变量名表列;
int main()
{
struct Student
{
int id;
char* name;
int age;
float score;
}student1, student2;
}
2.第二种
先声明结构体类型 再定义该类型的变量
int main()
{
struct Student
{
int id;
char* name;
int age;
float score;
};
struct Student student1, student2;
}
二.初始化和引用结构体
这里需要区分结构体类型和结构体变量 上面的struct Student是结构体类型相当于int double之类,student1, student2相当于定义的变量
1. “.”运算符对成员赋值
student.id=20230110;
“.”的运算优先级最高,所以可以把student.id(结构体变量名.成员名)当作一个变量来看待,就可以进行各种运算。
2.只能对最低级的成员进行运算
如果成员本身属于一个结构体类型,则要使用多个成员运算符直到最低级成员,如
student1.birthday.month
3.引用结构体变量或变量成员的地址
scanf("%d", &student1.id);//输入成员的值
printf("%o", &student1);//输出结构变量student1的地址
二.结构体数组
1.定义和引用结构体数组
a.struct结构体名
{成员}数组名[N];
struct Student
{
int id;
char* name;
int age;
float score;
}student[10];
b.先声明struct Student student [10];再引用
2.初始化
在定义数组后面加上={初值表列}
struct Person
{
char name[20];
int cnt;
}leader[3];
struct Person leader[3] = { {"Li",0},{"wang",0},{"liu",0 }};
三.结构体指针
1.指向结构体变量的指针
struct Student
{
int num;
}stu_1;
struct Student* p;//定义一个指向struct Student类型的指针变量
p = &stu_1;//令p指向stu_1
stu_1.num = 100;
printf("%d\n", (*p).num);//输出stu_1中的成员num
printf("%d\n",p->num);
printf("%d\n", stu_1.num);
输出结果均为100,说明(*p).num), p->num ,stu_1.num是等价的, p->num 就是指针p指向num成员,一般采用箭头指向方式更简易清晰
2.指向结构体数组的指针
struct Student {
int num;
char name[20];
int age;
};
struct Student stu[2] = { {01,"Li",20},{03,"Han",18} };
struct Student* p;
for (p = stu; p < stu + 2; p++) //先令p指向stu[0],然后就是指针数组的基本运算
{
printf("num=%d name=%s age=%d\n", p->num, p->name, p->age);
}
四.typedf定义新类型
基本形式为typedf+数据类型+类型变量名
1.用typedef建立新类型代替原有类型
typedef int Integer;//用Integer代替int型
typedef float Real;//用Real代替float型
int i, j;Integer i,j;//等价
float a, b; Real a, b;//等价
这里Integer代替了int,Real代替了float,作用是一样的。
这里typedf的作用还不太明显,所以下面用typedef定义代替复杂类型就好用多了。
2.typedef建立简单类型代替复杂类型
习惯用typedf声明的类型名的第一个字母用大写字母表示
1)定义新数组类型:
typedef int Num[100];
Num a;//a为包含100个元素的整形数组
2)定义新指针类型:
typedef char* String;
String a;//a为字符型指针数组
3)定义新结构体类型
可以直接定义,引用时就不用struct Date而是直接类型名Date:
typedef struct {
int month;
int day;
}Date;//定义了一个Date类型代表上面的结构体类型
Date birthday;//Date是结构体类型 birthday是Date类型的结构体变量
Date* p;
也可以定义完再重新用typedef定义
struct Student {
int id;
char* nmae;
};
typedef struct Student Student;
Student a;
Student* p;
五.链表
链表是由多个结点组成的,包括头指针head和表尾,每个结点由数据和下一节点的地址组成
1.静态链表
类似循环的模式,使p不断指向下一个结点的地址,这就需要结构体中的next成员指向另一个结构体(嵌套),直至最后一个NULL停止
如下建立有三位同学的静态链表
struct Student {
int num;
float score;
struct Student* next;
};
struct Student a, b, c, * head, * p;
a.num = 01; a.score = 90;
b.num = 02; b.score = 95;
c.num = 03; c.score = 98;
head = &a;
a.next = &b;
b.next = &c;
c.next = NULL;
p = head;
while (p != NULL) {
printf("%ld %2.lf\n", p->num, p->score);
p = p->next;//从最开始的a.next顺次指向下一结点,遍历链表
}
2.动态链表
从无到有一个一个开辟结点和输入数据,涉及到动态内存分配
补:动态内存分配
#include <stdlib.h>
int main()
{
int num=10;
int* a;
a = (int*)malloc(num * sizeof(int));//动态内存分配,让a拥有你想要的空间
for (int i = 0; i < num - 1; i++) {
scanf("%d", &a[i]);
}
for (int i = num-1; i >=0; i--) {
printf("%d", a[i]);
}
free(a);//释放内存
return 0;
}
1).(int*)是强制转换数据类型,让malloc函数转为int型
2).malloc()括号中的数字为开辟的字节数,如果要存入数据,须以数据个数数据类型所占用的字节数如:num*sizeof(int/float/char)
3)free()释放指针变量a所指向的空间
动态链表我也不太理解 但是把组建一个动态链表的代码如下表示出来:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#define LEN sizeof(struct Student)
struct Student {
int num;
float score;
struct Student* next;
};
int n;//全局变量
struct Student* creat(void)
{
struct Student* head=NULL;
struct Student* p1, *p2;
n = 0;
p1 = p2 = (struct Student*)malloc(LEN);
scanf("%d ,%f", &p1->num, &p2->score);
while (p1->num != NULL) {
n += 1;
if (n == 1) {
head = p1;
}
else {
p2->next = p1;
}
p2 = p1;
p1 = (struct Student*)malloc(LEN);
scanf("%d %f", &p1->num, &p1->score);
}
p2->next = NULL;
return(head);
}