【C语言】struct结构体保姆级别教学!

目录

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);


创作不易,感谢观看 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值