《小猫猫大课堂》三轮4——自定义类型(位段,枚举,联合)(内含通讯录)

news/2024/11/25 16:54:10/

宝子,你不点个赞吗?不评个论吗?不收个藏吗?

最后的最后,关注我,关注我,关注我,你会看到更多有趣的博客哦!!!

喵喵喵,你对我真的很重要。

目录

前言

位段

枚举

联合(共用体)

通讯录

0.源码(解说见后)

1.创建文件

2.打印菜单,明确功能

3.创建通讯录

4.初始化通讯录和添加联系人

5.展示通讯录

 6.删除指定联系人

7.查找指定联系人 

8.修改指定联系人

9.联系人排序

10.删除所有联系人

总结


前言

闹腾太久了,累了,小喵想静静,想抱抱自己。


位段

位段的声明和结构(结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。)是类似的,有两个不同:

1.位段的成员必须是 int、char,unsigned int 或signed int 。(同类型)

2.位段的成员名后边有一个冒号和一个数字。

位段的位是二进制位
struct A
{int _a:2;//两个比特位int _b:5;int _c:10;//10个比特位int _d:30;//单个成员不能超过32,因为一个整形32个比特位
};
int main()
{
printf("%d\n", sizeof(struct A));//结果是8
return 0;
}

和结构体一样,该怎么用,一样用,只是位段更节省空间

位段的内存分配:

1. 位段的成员可以是 int unsigned int signed int 或者是 char (属于整形家族)类型

2. 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的。

3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。

位段的跨平台问题:(不同平台,写不同代码,这也是结构体的又是,它可以跨平台)

1. int 位段被当成有符号数还是无符号数是不确定的。

2. 位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32,写成27,在16位机 器会出问题。

3. 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。

4. 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是 舍弃剩余的位还是利用,这是不确定的。


枚举

枚举顾名思义就是一一列举。 把可能的取值一一列举

enum Day//星期
{Mon,Tues,Wed,Thur,Fri,Sat,Sun
};
enum Sex//性别
{MALE,FEMALE,SECRET
};
enum Color//颜色
{RED,GREEN,BLUE
};

以上定义的 enum Day , enum Sex , enum Color 都是枚举类型。 {}中的内容是枚举类型的可能取值,也叫 枚举常量

这些可能取值都是有值的,默认从0开始,一次递增1,当然在定义的时候也可以赋初值。

enum Color//颜色
{RED,    //0GREEN,   //1BLUE     //2
};
enum Color//颜色
{RED=1,GREEN=2,BLUE=4
};

枚举的优点:

1. 增加代码的可读性和可维护性

2. 和#define定义的标识符比较枚举有类型检查,更加严谨。

3. 防止了命名污染(封装)

4. 便于调试

5. 使用方便,一次可以定义多个常量

现实生活中,我们能用枚举就用枚举。

enum Color//颜色
{RED=1,GREEN=2,BLUE=4
};
enum Color clr = GREEN;//只能拿枚举常量给枚举变量赋值,才不会出现类型的差异。
clr = 5;               //ok??

联合(共用体)

联合也是一种特殊的自定义类型 这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以联合也叫共用体)。(成员不能同时一起用空间)

联合的特点:

联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联 合至少得有能力保存最大的那个成员)

联合大小的计算:

  • 联合的大小至少是最大成员的大小。
  • 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。


通讯录

0.源码(解说见后)

//Contact.h
#pragma once
#define MAX 1000
#define NAME_MAX 20
#define SEX_MAX 5
#define ADDR_MAX 30
#define TELE_MAX 12#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<stdlib.h>//人的信息
typedef struct PeoInfo
{char name[NAME_MAX];int age;char sex[SEX_MAX];char addr[ADDR_MAX];char tele[TELE_MAX];
}PeoInfo;struct contact
{struct PeoInfo data[NAME_MAX];int sz;//记录当前已经有的元素个数
};typedef struct Contact
{PeoInfo data[1000];//存放人的信息int sz;//当前已存放信息的个数
}Contact;
//初始化通讯录
void InitContact(Contact* pc);
//增加联系人
void AddContact(Contact*pc);//删除指定联系人
void DelContact(Contact* pc);
//显示通讯录
void ShowContact(const Contact* pc);
//查找指定联系人
void SearchContact(Contact* pc);
//修改指定联系人
void ModifyContact(Contact* pc);
//联系人排序
void SortContact(Contact* pc);
//删除所有联系人
void DeaContact(Contact* pc);
//Contact.c
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include"contact.h"
void InitContact(Contact* pc)
{assert(pc);pc->sz = 0;memset(pc->data, 0, sizeof(pc->data));
}void AddContact(Contact* pc)
{assert(pc);if (pc->sz == 1000){printf("通讯录已满,无法添加\n");return;}//增加一个人的信息printf("请输入名字:>");scanf("%s", pc->data[pc->sz].name);printf("请输入年龄:>");scanf("%d", &(pc->data[pc->sz].age));printf("请输入性别:>");scanf("%s", pc->data[pc->sz].sex);printf("请输入地址:>");scanf("%s", pc->data[pc->sz].addr);printf("请输入电话:>");scanf("%s", pc->data[pc->sz].tele);pc->sz++;
}void ShowContact(const Contact* pc)
{assert(pc);int i = 0;printf("%-20s\t%-4s\t%-5s\t%-20s\t%-15s\n", "名字", "年龄", "性别", "地址", "电话");for (i = 0; i < pc->sz; i++){printf("%-20s\t%-4d\t%-5s\t%-20s\t%-15s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].addr, pc->data[i].tele);}}int FindByName(const Contact* pc, char name[])
{assert(pc);int i = 0;for (i = 0; i < pc->sz; i++){if (strcmp(pc->data[i].name, name) == 0){return i;}}return -1;
}void DelContact(Contact* pc)
{assert(pc);char name[NAME_MAX] = { 0 };if (pc->sz == 0){printf("通讯录为空,无法删除");return;}//删除//找出要删除的人printf("请输入要删除的人的名字;>");scanf("%s", name);int ret=FindByName(pc, name);if (-1 == ret){printf("要删除的人不存在\n");return;}int i = 0;int del = 0;for (i = 0; i < pc->sz; i++){if (strcmp(pc->data[i].name, name) == 0){del = i;break;}}//删除for (i = del; i < pc->sz; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("删除成功\n");
}void SearchContact(const Contact* pc)
{assert(pc);char name[NAME_MAX] = { 0 };printf("请输入要查找人的名字:>");scanf("%s", name);int pos = FindByName(pc, name);if (-1 == pos){printf("要查找的人不存在\n");return;}//打印信息printf("%-20s\t%-4s\t%-5s\t%-20s\t%-15s\n", "名字", "年龄", "性别", "地址", "电话");printf("%-20s\t%-4d\t%-5s\t%-20s\t%-15s\n", pc->data[pos].name, pc->data[pos].age, pc->data[pos].sex, pc->data[pos].addr, pc->data[pos].tele);
}void ModifyContact(Contact* pc)
{assert(pc);char name[NAME_MAX] = { 0 };printf("请输入要删除的人的名字;>");scanf("%s", name);int pos = FindByName(pc, name);if (-1 == pos){printf("要删除的人不存在\n");return;}printf("请输入名字:>");scanf("%s", pc->data[pos].name);printf("请输入年龄:>");scanf("%d", &(pc->data[pos].age));printf("请输入性别:>");scanf("%s", pc->data[pos].sex);printf("请输入地址:>");scanf("%s", pc->data[pos].addr);printf("请输入电话:>");scanf("%s", pc->data[pos].tele);printf("修改完成\n");
}//排序函数//1.按照姓名进行排序
int Conpare_ByName(const void* e1, const void* e2)
{return strcmp(((struct PeoInfo*)e1)->name, ((struct PeoInfo*)e2)->name);
}
//2.按照年龄进行排序
int Conpare_ByAge(const void* e1, const void* e2)
{return ((struct PeoInfo*)e1)->age - ((struct PeoInfo*)e2)->age;
}
//3.按照住址进行排序
int Conpare_ByAddress(const void* e1, const void* e2)
{return strcmp(((struct PeoInfo*)e1)->addr, ((struct PeoInfo*)e2)->addr);
}
void SortContact(Contact* pc)
{assert(pc);printf("请选择你想排序的方式:\n");printf("1.姓名\n2.年龄\n3.住址\n");int input = 0;scanf("%d", &input);switch (input){case 1:qsort(pc->data, pc->sz, sizeof(pc->data[0]), Conpare_ByName);printf("排序成功\n");break;case 2:qsort(pc->data, pc->sz, sizeof(pc->data[0]), Conpare_ByAge);printf("排序成功\n");break;case 3:qsort(pc->data, pc->sz, sizeof(pc->data[0]), Conpare_ByAddress);printf("排序成功\n");break;}
}void DeaContact(Contact* pc)
{assert(pc);memset(pc->data, 0, sizeof(pc->data));pc->sz == 0;printf("清空成功!\n");}
//teat.c
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include"contact.h"
void menu()
{printf("*********************************\n");printf("*****   1.add     2.del    ******\n");printf("*****   3.search  4.modify ******\n");printf("*****   5.show    6.sort   ******\n");printf("*****   7.dea     0.exit   ******\n");printf("*********************************\n");
}
int main()
{int input = 0;//创建通讯录PeoInfo  data[1000];int sz=05l;Contact con;//初始化通讯录InitContact(&con);do{menu();printf("请选择->");scanf("%d", &input);switch (input){case  1:AddContact(&con);break;case  2:DelContact(&con);break;case  3:SearchContact(&con);break;case  4:ModifyContact(&con);break;case  5:ShowContact(&con);break;case  6:SortContact(&con);break;case  7:DeaContact(&con);break;case  0:printf("退出游戏");break;default:printf("选择错误");break;}} while (input);return 0;
}

1.创建文件

test.c——测试通讯录

contact.c——通讯录的实现

contact.h——函数的声明


2.打印菜单,明确功能

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include"contact.h"
void menu()
{printf("*********************************\n");printf("*****   1.add     2.del    ******\n");printf("*****   3.search  4.modify ******\n");printf("*****   5.show    6.sort   ******\n");printf("*****   7.sort    0.exit   ******\n");printf("*********************************\n");
}
int main()
{int input = 0;do{menu();printf("请选择->");scanf("%d", &input);switch (input){case  1:break;case  2:break;case  3:break;case  4:break;case  5:break;case  6:break;case  7:break;case  0:printf("退出游戏");break;default:printf("选择错误");break;}} while (input);return 0;
}

3.创建通讯录

//头文件
#pragma once
//人的信息
typedef struct PeoInfo
{char name[20];int age;char sex[5];char addr[30];char tele[12];
}PeoInfo;typedef struct Contact
{PeoInfo data[1000];//存放人的信息int sz;//当前已存放信息的个数
}Contact;

4.初始化通讯录和添加联系人

test.c

 

//Contact.c
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include"contact.h"
void InitContact(Contact* pc)
{pc->sz = 0;memset(pc->data, 0, sizeof(pc->data));
}AddContact(Contact* pc)
{if (pc->sz == 1000){printf("通讯录已满,无法添加\n");return;}//增加一个人的信息printf("请输入名字:>");scanf("%s", pc->data[pc->sz].name);printf("请输入年龄:>");scanf("%d", &(pc->data[pc->sz].age));printf("请输入性别:>");scanf("%s", pc->data[pc->sz].sex);printf("请输入地址:>");scanf("%s", pc->data[pc->sz].addr);printf("请输入电话:>");scanf("%s", pc->data[pc->sz].tele);pc->sz++;
}

5.展示通讯录

test.c

头文件声明

//Contact.c(实现)
void ShowContact(Contact* pc)
{int i = 0;for (i = 0; i < pc->sz; i++){printf("%s\t%d\t%s\t%s\t%s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].addr, pc->data[i].tele);}}

阶段性测试(输入数据可使用中文)  

 数据右对齐

void ShowContact(Contact* pc)
{int i = 0;for (i = 0; i < pc->sz; i++){printf("%20s\t%4d\t%5s\t%20s\t%15s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].addr, pc->data[i].tele);}}

数据左对齐

void ShowContact(Contact* pc)
{int i = 0;for (i = 0; i < pc->sz; i++){printf("%-20s\t%-4d\t%-5s\t%-20s\t%-15s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].addr, pc->data[i].tele);}}

加表头明确数据

void ShowContact(Contact* pc)
{int i = 0;printf("%-20s\t%-4s\t%-5s\t%-20s\t%-15s\n", "名字", "年龄", "性别", "地址", "电话");for (i = 0; i < pc->sz; i++){printf("%-20s\t%-4d\t%-5s\t%-20s\t%-15s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].addr, pc->data[i].tele);}}

 6.删除指定联系人

先声明(Contact.h)

 引用删除的子程序(test.h)

 Contact.c

void DelContact(Contact* pc)
{char name[NAME_MAX] = { 0 };if (pc->sz == 0){printf("通讯录为空,无法删除");return;}//删除//找出要删除的人printf("请输入要删除的人的名字;>");scanf("%s", name);int i = 0;int del = 0;for (i = 0; i < pc->sz; i++){if (strcmp(pc->data[i].name, name) == 0){del = i;break;}}//删除for (i = del; i < pc->sz; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("删除成功\n");
}

阶段性测试:

如果删除的联系人不存在,要做出提示

应该先找出需删除的联系人,判断其是否存在。

int FindByName(const Contact* pc, char name[])
{int i = 0;for (i = 0; i < pc->sz; i++){if (strcmp(pc->data[i].name, name) == 0){return i;}}return -1;
}void DelContact(Contact* pc)
{char name[NAME_MAX] = { 0 };if (pc->sz == 0){printf("通讯录为空,无法删除");return;}//删除//找出要删除的人printf("请输入要删除的人的名字;>");scanf("%s", name);int ret=FindByName(pc, name);if (-1 == ret){printf("要删除的人不存在\n");return;}int i = 0;int del = 0;for (i = 0; i < pc->sz; i++){if (strcmp(pc->data[i].name, name) == 0){del = i;break;}}//删除for (i = del; i < pc->sz; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("删除成功\n");
}

 阶段性测试(判断代码实现效果)


7.查找指定联系人 

记得声明和引用哈

void SearchContact(const Contact* pc)
{char name[NAME_MAX] = { 0 };printf("请输入要查找人的名字:>");scanf("%s", name);int pos = FindByName(pc, name);if (-1 == pos){printf("要查找的人不存在\n");return;}//打印信息printf("%-20s\t%-4s\t%-5s\t%-20s\t%-15s\n", "名字", "年龄", "性别", "地址", "电话");printf("%-20s\t%-4d\t%-5s\t%-20s\t%-15s\n", pc->data[pos].name, pc->data[pos].age, pc->data[pos].sex, pc->data[pos].addr, pc->data[pos].tele);
}

阶段性测试


8.修改指定联系人

记得声明和引用哈

void ModifyContact(Contact* pc)
{assert(pc);char name[NAME_MAX] = { 0 };printf("请输入要删除的人的名字;>");scanf("%s", name);int pos = FindByName(pc, name);if (-1 == pos){printf("要删除的人不存在\n");return;}printf("请输入名字:>");scanf("%s", pc->data[pos].name);printf("请输入年龄:>");scanf("%d", &(pc->data[pos].age));printf("请输入性别:>");scanf("%s", pc->data[pos].sex);printf("请输入地址:>");scanf("%s", pc->data[pos].addr);printf("请输入电话:>");scanf("%s", pc->data[pos].tele);printf("修改完成");
}

阶段性测试: 


9.联系人排序

记得声明和引用哈

//排序函数//1.按照姓名进行排序
int Conpare_ByName(const void* e1, const void* e2)
{return strcmp(((struct PeoInfo*)e1)->name, ((struct PeoInfo*)e2)->name);
}
//2.按照年龄进行排序
int Conpare_ByAge(const void* e1, const void* e2)
{return ((struct PeoInfo*)e1)->age - ((struct PeoInfo*)e2)->age;
}
//3.按照住址进行排序
int Conpare_ByAddress(const void* e1, const void* e2)
{return strcmp(((struct PeoInfo*)e1)->addr, ((struct PeoInfo*)e2)->addr);
}
void SortContact(Contact* pc)
{assert(pc);printf("请选择你想排序的方式:\n");printf("1.姓名\n2.年龄\n3.住址\n");int input = 0;scanf("%d", &input);switch (input){case 1:qsort(pc->data, pc->sz, sizeof(pc->data[0]), Conpare_ByName);printf("排序成功\n");break;case 2:qsort(pc->data, pc->sz, sizeof(pc->data[0]), Conpare_ByAge);printf("排序成功\n");break;case 3:qsort(pc->data, pc->sz, sizeof(pc->data[0]), Conpare_ByAddress);printf("排序成功\n");break;}
}


10.删除所有联系人

记得声明和引用哈

void DeaContact(Contact* pc)
{assert(pc);memset(pc->data, 0, sizeof(pc->data));pc->sz == 0;printf("清空成功!\n");}


总结

即使结束也是开始,来,我们干了这碗鸡汤。


宝子,你不点个赞吗?不评个论吗?不收个藏吗?

最后的最后,关注我,关注我,关注我,你会看到更多有趣的博客哦!!!

喵喵喵,你对我真的很重要。 


http://www.ppmy.cn/news/22773.html

相关文章

算法刷题打卡第82天:计算布尔二叉树的值

计算布尔二叉树的值 难度&#xff1a;简单 给你一棵 完整二叉树 的根&#xff0c;这棵树有以下特征&#xff1a; 叶子节点 要么值为 0 要么值为 1 &#xff0c;其中 0 表示 False &#xff0c;1 表示 True 。非叶子节点 要么值为 2 要么值为 3 &#xff0c;其中 2 表示逻辑或…

实现加盐加密

实现加盐加密存储密码1. MD52. 加盐加密实现&#xff1a;1&#xff09;修改 password 为 64 位字符串2&#xff09;创建 SecurityUtil 类 (加盐加密类)应用存储密码 1. MD5 Spring 提供了库 import org.springframework.util.DigestUtils; &#xff0c;我们可以进行 MD5 加密&…

react源码中的生命周期和事件系统

这一章我想跟大家探讨的是React的生命周期与事件系统。 jsx的编译结果 因为前面也讲到jsx在v17中的编译结果&#xff0c;除了标签名&#xff0c;其他的挂在标签上的属性&#xff08;比如class&#xff09;&#xff0c;事件&#xff08;比如click事件&#xff09;&#xff0c;都…

Attention-自注意机制

Attention-自注意机制 Attention 可以大幅提升seq2seq的遗忘问题。有了Attention&#xff0c;Seq2Seq 模型不会忘记源输入&#xff0c;且decoder解码器就知道该把注意力集中在哪里。 缺点: 计算量大得多 Original paper: • Bahdanau,Cho,& Bengio. Neural machine trans…

React中的jsx语法转换后生成虚拟DOM,再挂载到真实的DOM中的全过程讲解

前言 react中的jsx语法很多伙伴都会使用&#xff0c; 但是你知道它的本质是什么吗&#xff1f;运行中它会做如何的转换呢&#xff1f;jsx内部又是怎么生成了虚拟DOM&#xff1f;虚拟DOM又是如何挂载到真实DOM上去的呢&#xff1f; 带着这些问题&#xff0c;我们做个讲解把&…

python图形化开发教程

简介学习此教程必须先学习python入门教程&#xff08; Python入门教程_恰到好处a的博客-CSDN博客&#xff09;PySimpleGUI这个模块需要安装&#xff0c;在cmd输入pip install PySimpleGUI&#xff0c;在python中验证安装:输入import PySimpleGUI&#xff0c;看一看是否正常引入…

Android boot.img dtb.img 编译过程

最近做RK3588案子,修改dts后,导致boot.img过大,编译出错,整体分析下boot.img过大的原因是因为在打包boot.img过程中,dbt.img过大导致,所以整体分析下boot.img编译过程,尤其是dbt.img的生成过程.boot.img生成过程在Andorid跟目录下执行, source build/envsetup.sh 然后lunch xx(…

科技云报道:上云尚未成功,“下云潮”已悄然来临?

科技云报道原创。 云计算一直被视为是企业数字化转型的底座&#xff0c;很多企业都在通过加速数字化转型应对市场环境的动荡变化&#xff0c;一手抓降本增效&#xff0c;另一手也还在继续谋求突破式创新。 然而&#xff0c;经历这两年的疫情&#xff0c;活下去成为每一个企业的…