目录
1.格式,命名
2. 大小计算
3.应用
struct是一种结构体,用来保存较为复杂的变量信息,这种信息的特点通常是:类型多且杂,内容多,分散不易于调试
比如一个人的信息,我们想把他封装起来保存,这样易于读取,使分散的信息集中
1.格式,命名?
我们现在想要记录一个学生的信息:学号1234,姓名lily,年级14,性别female
如何实现?
struct Student
{
char ID[10];
char name[10];
int age;
char gender[10];
};
int main()
{
struct Student l = { "1234","Lily",14,"female" };
printf("%s %s %d %s", l.ID, l.name, l.age, l.gender);
}
?请注意这里一些基本的语法结构,包括初始化的方式(花括号),创建结构体的方式,结构体成员访问的细节
当然在我之前的博客已经分享过这个细节,https://blog.csdn.net/weixin_71138261/article/details/126071887?spm=1001.2014.3001.5501
这里不在赘述了?
2. 大小计算
关于结构体的大小计算才是本篇文章的重难点!!
首先,结构体也是有大小的
struct A
{
int a;
short b;
int c;
char d;
};
struct B
{
int a;
short b;
char c;
int d;
};
int main()
{
printf("%d %d", sizeof(struct A), sizeof(struct B));
}
首先我们思考一下,应该是多少呢
直观来说,
对于struct A : int a? ?4字节? short b? ?2字节??int c? ?4字节? char d? 1字节
4+2+4+1=11
对于struct B:int a? ?4字节? ??short b? 2字节? ?char c? 1字节? ?int d? ?4字节
4+2+1+4=11
?那结果是这样吗?
居然一个都没对
到底是什么计算规则呢?
首先普及一下最最基本的规则 (你要从心底里接受它):对齐数,单位是字节(一下谈论的都是字节)
每个平台都有默认的对齐数
我现在使用的是vs2022,他的默认对齐数是8
每个结构体成员都有自己的类型,也就是自己的对齐数
自身的对齐数肯定会和默认对齐数冲突,那么我们到底在计算大小的时候听谁的?
谁小听谁的!!!!!!!!!!!!!!!
比如int? 自身对齐数是4,平台默认对齐数是8
所以int 最终的对齐数就是4
那么数组怎么办?和元素个数有关
?下一个很重要的概念:偏移量!
我们知道了各种类型的对齐数之后,到底他们是和谁对齐的呢?
是相对于0而言的,这个0是我们为了方便计算假想出来的,每个类型的对齐数就代表了他的偏移量
第一个偏移就是相对于0开始的
先掌握这两个概念之后,我们回头看一下上面的例子
一定要注意图片里的补充规则
那么自己算一下struct B的大小吧
?
如果大家怕默认对齐数不对的话可以自己检查
用offsetof这个函数
#include <stddef.h>
int main()
{
printf("%d\n", sizeof(struct Book));
printf("%d\n",(int) offsetof(struct Book,page));
printf("%d\n", (int)offsetof(struct Book,name));
printf("%d\n", (int)offsetof(struct Book,writer));
}
这个函数可以帮助你计算每个结构体成员的起始偏移量
难道每个平台就这么霸道吗?
注意:Linu系统没有默认对齐数,就是成员自身类型
其实我们可以修改默认对齐数
#include <stdio.h>
#include <stddef.h>
//modifier fixed alignment number
//offsetof is a fonction to calculate the type shall be a structure or union type.
struct Book
{
char name[20];
int page;
char writer[20];
};
//if I wanna change the alignment number
# pragma pack(1)
int main()
{
printf("%d\n", sizeof(struct Book));
printf("%d\n",(int) offsetof(struct Book,page));
printf("%d\n", (int)offsetof(struct Book,name));
printf("%d\n", (int)offsetof(struct Book,writer));
}
通过#progma pack(1)把默认对齐数修改成1,这样所有类型都是紧挨着填充,不会出现浪费
3.应用?
?其实我们可以感受到struct的重要性,这样生活中很多东西都可以封装,比如一本书,一个教室
那么我们来看一下用struct实现通讯录储存联系人的信息
//contact.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include "contact.h";
void Init(struct conster*p)
{
assert(p);
p->sz = 0;
memset(p->date, 0, sizeof(struct information) * MAX);
}
void Add(struct conster* p)
{
assert(p);
if (p->sz == 100)
{
printf("lack of memory !\n");
return;
}
else
{
printf("Please input the name \n");
scanf("%s", &(p->date[p->sz].name));
printf("Please input the gender \n");
scanf("%s", &(p->date[p->sz].gender));
printf("Please input the age\n");
scanf("%d", &(p->date[p->sz].age));
printf("Please input the tele \n");
scanf("%s", &(p->date[p->sz].tele));
printf("Please input the adress\n");
scanf("%s", &(p->date[p->sz].adress));
p->sz++;
printf("success\n");
}
}
void Show(struct conster* p)
{
printf("%-20s\t%-5s\t%-5s\t%-20s\t%-20s\n", "name", "gender", "age", "telephone", "adress");
for(int i=0;i<(p->sz);i++)
{
printf("%-20s\t%-5s\t%-5d\t%-20s\t%-20s\n", p->date[i].name, p->date[i].gender, p->date[i].age, p->date[i].tele, p->date[i].adress);
}
}
int search_by_name(char* name,struct conster *p)
{
for (int i = 0; i < p->sz; i++)
{
if (strcmp(name, p->date[i].name) == 0)
//return 1; //不能简单这样,需要记录要删除元素具体在通信录的位置
return i;
}
return -1;
}
void Del(struct conster* p)
{
char name[20] = { 0 };
printf("Please input the name\n");
scanf("%s", name);
int ret= search_by_name(name ,p);
if (ret!=-1)
{
int j = 0;
for (j = ret; j < p->sz - 1; j++)
{
p->date[j] = p->date[j + 1];
}
p->sz--;
printf("success\n");
}
else
{
printf("There isn't the member!\n");
}
}
void Mod(struct conster* p)
{
char name[20] = { 0 };
printf("Please input the name\n");
scanf("%s", name);
int ret = search_by_name(name, p);
if (ret != -1)
{
int choice = 0;
printf("** 1.name ** 2.gender ** 3.age ** 4.tele ** 5.adress**\n");
scanf("%d", &choice);
switch (choice)
{
case 1:
{
printf("Please input the name of the member who you want to modifier\n");
scanf("%s", &(p->date[ret].name));
break;
}
case 2:
{
printf("Please input the gender of the member who you want to modifier\n");
scanf("%s", &(p->date[ret].gender));
break;
}
case 3:
{
printf("Please input the age of the member who you want to modifier\n");
scanf("%d", &(p->date[ret].age));
break;
}
case 4:
{
printf("Please input the telephone of the member who you want to modifier\n");
scanf("%s", &(p->date[ret].tele));
break;
}
case 5:
{
printf("Please input the adress of the member who you want to modifier\n");
scanf("%s", &(p->date[ret].adress));
break;
}
}
printf("success\n");
}
else
{
printf("There isn't the member!\n");
}
}
void Search(struct conster* p)
{
char name[20] = { 0 };
printf("Please input the name\n");
scanf("%s", name);
int ret = search_by_name(name, p);
if (ret != -1)
{
printf("%-20s\t%-5s\t%-5s\t%-20s\t%-20s\n", "name", "gender", "age", "telephone", "adress");
printf("%-20s\t%-5s\t%-5d\t%-20s\t%-20s\n", p->date[ret].name, p->date[ret].gender, p->date[ret].age, p->date[ret].tele, p->date[ret].adress);
}
else
{
printf("There isn't the member!\n");
}
}
void All_cls(struct conster *p)
{
assert(p);
p->sz = 0;
memset(p->date, 0, sizeof(struct information) * MAX);
printf("%-20s\t%-5s\t%-5s\t%-20s\t%-20s\n", "name", "gender", "age", "telephone", "adress");
printf("%-20s\t%-5s\t%-5d\t%-20s\t%-20s\n", p->date[0].name, p->date[1].gender, p->date[2].age, p->date[3].tele, p->date[4].adress);
}
int comper(const void* p1, const void* p2)
{
return (*(int*)p1 - *(int*)p2); //把小的放前
}
void Sort(struct conster* p)
{
qsort(p->date, p->sz, sizeof(struct information), comper);
printf("success\n");
}
//main.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include "contact.h"
void menu()
{
printf("********* 1.Add ******** 2.Delate *********\n");
printf("********* 3.Modifier *** 4.Search *********\n");
printf("********* 5.Show ******* 6.all cls *********\n");
printf("********* 7.sort ******* 0.exit *********\n");
}
int main()
{
//struct information date[MAX]; //创建一百个人的信息
struct conster con; //创建通讯录
Init(&con); //初始化
int num = 0;
do {
menu();
printf("Please input your number\n");
scanf("%d", &num);
switch (num)
{
case 1:
Add(&con);
break;
case 2:
Del(&con);
break;
case 3:
Mod(&con);
break;
case 4:
Search(&con);
break;
case 5:
Show(&con);
break;
case 6:
All_cls(&con);
break;
case 7:
Sort(&con);
break;
case 0:
printf("Bye~\n");
break;
default :
printf("Please input agine\n");
break;
}
} while (num);
return 0;
}
//contact.h
#pragma once
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#define MAX 10
struct information
{
//姓名、性别、年龄、电话、住址
char name[20];
char gender[5];
int age;
int tele[20];
char adress[20];
};
struct conster
{
int sz;
struct information date[MAX]; //存放十个人的信息
};
void Init(struct conster* p);
void Add(struct conster* p);
void Show(struct conster* p);
void Del(struct conster* p);
void Mod(struct conster* p);
void All_cls(struct conster* p);
void Sort(struct conster* p);
int search_by_name(char* name, struct conster* p);
void Search(struct conster* p);
创作不易,感谢观看?
|