动漫女性角色引发热议:艺术边界与文化解读的交织

核心内容摘要

致敬韩寒,成年人的世界里,我们都是那个披荆斩棘的少年
《地下偶像NASA》:当星辰触碰心跳,一场关于梦想与现实的樱花之约

fulao2轻量版检测线路1

目录

前景提要及灵感来源

预备知识

1顺序表的定义与结构特点

2顺序表的结构

3顺序表的基本操作

定义通讯录的数据结构

通讯录操作方法设计

1通讯录初始化

2通讯录的销毁

3通讯录的添加方法

4通讯录的删除

5通讯录的展示

6通讯录的查找

7通讯录的修改

用户交互功能与菜单设计

通讯录各项功能测试

1通讯录初始化测试

2通讯录的添加测试

3通讯录的删除和展示测试

4通讯录的修改测试

结语

前景提要及灵感来源学习了顺序表定义与结构以及顺序表相关方法之后很难不承认顺序表是一个很好的工具以数组为底层结构但是却自带了很多数组没有的方法例如头插(PushFront)尾插(PushBack),头删(PopFront)等等那么顺序表具体有什么用为了巩固顺序表的相关特点和方法笔者将全过程讲解基于顺序表实现简易通讯录。

通讯录的需求分析功能需求(添加联系人删除联系人查找联系人修改联系人信息数据存储需求(姓名电话年龄地址等)。

不难发现在实现功能需求上顺序表具有明显的优势接下来的许多方法实现实际上是对顺序表方法的封装复用。

如果我们以单个联系人为元素存储那么顺序表不就被我们改装成通讯录了嘛

预备知识

1顺序表的定义与结构特点顺序表是线性表的一种以数组为底层结构对数组进行封装实现了增删查改等接口。

顺序表的数据类型是结构体(用结构体定义。

顺序表分为静态顺序表和动态顺序表静态顺序表的底层为一个定长数组动态顺序表包含了一个指向某一数据类型数组的指针如果是以整形数据为底层结构那么该指针就是int*类型如果是以字符数组为底层结构那么该指针就是char*类型当然也可以是以自定义类型为元素进行存储那么相应的指针就是你说定义的结构体的指针类型。

2顺序表的结构定义顺序表的结构typedef int DataType #define N 10 //静态顺序表 strcut STSeqList { Datatype arr[N];//定长数组 int size;//有效数据个数 } //动态顺序表 typedef struct SeqList { DataType* arr; int size; //有效数据个数 int capacity; //顺序表空间大小 }SL;

3顺序表的基本操作SeqList.h​ //定义顺序表的结构 //静态顺序表 //封装了一个定长数组 typedef peoInfo DataType;//方便后续类型替换 //#define N 100 //struct SeqList //{ // DataType arr[N]; // //}; //动态顺序表 typedef struct SeqList { DataType* arr; int size; int capacity; }SL; //顺序表的初始化方法 void SLInit(SL* ps); //传址调用才能通过这个地址解引用访问顺序表结构体 //顺序表的销毁方法 void SLDestory(SL* ps); //检查空间大小方法 void SLCapacityCheck(SL* ps); //顺序表增删查改操作 //-------增加操作-------- //尾插 void SLPushBack(SL* ps, DataType X); //头插 void SLPushFront(SL* ps, DataType X); //顺序表打印方法 //void SLPrint(SL a); //头删 void SLPopFront(SL* ps); //尾删 void SLPopBack(SL* ps); //指定位置之前插入数据 void SLInsert(SL* ps, int pos, DataType X); //删除指定位置的数据 void SLErase(SL* ps, int pos); //查找指定数据 //int SLFind(SL* ps, DataType X); ​SeqList.c#define _CRT_SECURE_NO_WARNINGS #include SeqList.h #include assert.h //顺序表初始化方法 void SLInit(SL* ps) { ps-arr NULL; ps-size ps-capacity 0; } //顺序表销毁方法 void SLDestory(SL* ps) { assert(ps); if (ps-arr)//ps-arrNULL { free(ps-arr); } ps-arr NULL; ps-size ps-capacity 0; } //空间检查方法(不够时会申请空间 void SLCapacityCheck(SL* ps) { if (ps-size ps-capacity) { //申请空间用malloc realloc还是calloc //realloc用来增容 //三目表达式↓ int newcapacity ps-capacity 0 ? 4 : 2 * ps-capacity;//空间为空申请四个不够就加倍 DataType* tmp (DataType*)realloc(ps-arr, newcapacity * sizeof(DataType)); if (tmp NULL)//用一个临时的tmp变量解决realloc失败原空间变NULL的问题 { perror(tmp); exit(

; } ps-arr tmp; ps-capacity newcapacity; } } //尾插方法 void SLPushBack(SL* ps,DataType X) { //一种温柔的解决方式判断是否是空指针 //if (ps NULL) //{ // return; //} assert(ps);//暴力的解决方式 //插入前检查空间 SLCapacityCheck(ps); ps-arr[ps-size] X; } //头插方法 void SLPushFront(SL* ps, DataType X) { assert(ps); SLCapacityCheck(ps);//头插也要检查空间 //头插需要先让顺序表中的已有的数据整体往后挪动一位 for (int i ps-size; i 0; i--) { ps-arr[i] ps-arr[i - 1]; } ps-arr[0] X; ps-size;//SLPrint打印方法依赖于sizesize要改变 } void SLPrint(SL a) { for (int i 0; i a.size; i) { printf(%d , a.arr[i]); } printf(\n); } void SLPopBack(SL* ps) { assert(ps); assert(ps-size); --ps-size;//不影响增删查改所以直接让size-1 } void SLPopFront(SL* ps) { assert(ps); assert(ps-size); for (int i 0; i ps-size-1; i) { ps-arr[i] ps-arr[i 1]; } --ps-size; } void SLInsert(SL* ps, int pos, DataType X) { assert(ps); assert(pos 0 pos ps-size);//pos大于等于且要小于等于有效数据个数 //先检查空间够不够不够就申请空间 SLCapacityCheck(ps); //pos及以后的数据整体往后移动一位 for (int i ps-size; i pos; i--) { ps-arr[i] ps-arr[i - 1]; } ps-arr[pos] X; ps-size; } void SLErase(SL* ps, int pos) { assert(ps); assert(pos 0 pos ps-size);//和SLInsert不同因为size位置上无数据不可删除 //pos以后的数据整体向前移动一位 for (int i pos; i ps-size - 1; i) { ps-arr[i] ps-arr[i 1];//最后一步是arr[size-2]arr[size-1]; } ps-size--; } int SLFind(SL* ps, DataType X) { assert(ps); for (int i 0; i ps-size; i) { if (ps-arr[i] X) { //找到了 return i; } } //没找到 return -1; }

定义通讯录的数据结构定义联系人结构体包含姓名、年龄、电话等信息。

//联系人结构体包含了姓名、性别、年龄、电话、地址 typedef struct PersonInfo { char name[NAME_MAX]; char sex[SEX_MAX]; int age; char tel[TEL_MAX]; char addr[ADDR_MAX]; }peoInfo;//改名字方便使用 typedef struct SeqList contact;//整体改名为contact区别出来方便使用我们采用动态顺序表来实现typedef peoInfo DataType; typedef struct SeqList { DataType* arr; int size; int capacity; }SL;

通讯录操作方法设计

1通讯录初始化因为通讯录的初始化实际上就是顺序表的初始化所以我们直接调用了SeqList.h、SeqList.c顺序表方法中SLInit()//通讯录的初始化实际上就是顺序表的初始化 //直接调用顺序表初始化方法 void InitContact(contact* con) { SLInit(con); }

2通讯录的销毁和通讯录的初始化类似都是本质顺序表的初始化或者销毁所以也是直接调用了SLDestroy()方法//通讯录的销毁 void DestroyContact(contact* con) { SLDestory(con); }

3通讯录的添加方法通讯录的核心功能之一能够添加联系人以及联系人各项信息如名字电话等与上文顺序表的添加不同在于我们通讯录储存的是自定义类型所以在添加到通讯录这种顺序表前我们先要对自己要添加的联系人结构体进行初始化最后是直接复用了顺序表中的SLPushBack()尾插方法。

//通讯录的添加 void AddContact(contact* con) { peoInfo info; printf(请输入要添加的联系人姓名\n); scanf(%s, info.name); printf(请输入要添加的联系人性别\n); scanf(%s, info.sex); printf(请输入要添加的联系人年龄\n); scanf(%d, info.age); printf(请输入要添加的联系人电话\n); scanf(%s, info.tel); printf(请输入要添加的联系人地址\n); scanf(%s, info.addr); //以上代码实现创建一个联系人变量并通过输入初始化好 //为后面的pushback到通讯录顺序表做准备 SLPushBack(con, info); }

4通讯录的删除一个简单的通讯录还需要具备能够删除指定联系人的功能为了实现这一功能:删除指定联系人指定的意思也就是我们要提供一些这个我们要删除联系人的信息供程序查找通讯录中有无这个联系人数据如果有就返回联系人在通讯录的位置下标如果没有返回一个小于0的值如-1标记为通讯录没有要删除的联系人的数据的依据。

通过名字查找联系人代码如下//按照名字查找方法查出数据所对应的下标返回下标 //如果数据不存在就返回一个小于0的值-1 int FindByName(contact* con, char name[]) { for (int i 0; i con-size; i) { if (0 strcmp(con-arr[i].name, name)) { return i; } } return -1; }删除方法如下//通讯录的删除 void DelContact(contact* con) { //删除联系人 //删除指定的联系人 //先要找到联系人位置 //通过联系人下标删除 //如何联系人不存在就返回一个-1,代表联系人不存在 char name[NAME_MAX]; printf(请输入要删除的联系人姓名:\n); scanf(%s, name); int find FindByName(con, name); if (find -

{ printf(要删除的联系人数据不存在!\n); return; } SLErase(con,find); printf(删除成功\n); }

5通讯录的展示前面所写到的方法都是需要及时的测试其中为了直观的展示通讯录的添加删除是否成功我们需要将通讯录中联系人信息打印出来//通讯录的展示 void ShowContact(contact* con) { //先打印表头 printf(%s %s %s %s %s\n, 姓名., 性别, 年龄, 电话, 地址); for (int i 0; i con-size; i) { printf(%3s %3s %3d %3s %3s\n,//手动调整一下格式 con-arr[i].name, con-arr[i].sex, con-arr[i].age, con-arr[i].tel, con-arr[i].addr); } }

6通讯录的查找有时候我们不需要展示出所有联系人的信息只需要找到某一个联系人如果该联系人在通讯录中就能被我们找到并且打印出他的各项信息//通讯录的查找 void FindContact(contact* con) { char name[NAME_MAX]; printf(请输入要查找的联系人姓名:\n); scanf(%s, name); int findFindByName(con, name); if (find

{ printf(要查找的联系人数据不存在\n); return; } printf(%s %s %s %s %s\n, 姓名., 性别, 年龄, 电话, 地址); printf(%3s %3s %3d %3s %3s\n,//手动调整一下格式 con-arr[find].name, con-arr[find].sex, con-arr[find].age, con-arr[find].tel, con-arr[find].addr); }

7通讯录的修改一个常见的场景是在我们将某个联系人添加到通讯录中我们可能存错了他的名字或电话等信息那么我们希望我们的通讯录具备通讯录的修改功能//通讯录的修改 void ModifyContact(contact* con) { char name[NAME_MAX]; printf(请输入你要修改的联系人的姓名!\n); scanf(%s, name); int find FindByName(con, name); if (find

{ printf(要修改的联系人数据不存在\n); } //直接修改 printf(请输入新的姓名\n); scanf(%s, con-arr[find].name); printf(请输入新的性别\n); scanf(%s, con-arr[find].sex); printf(请输入新的年龄\n); scanf(%d, con-arr[find].age); printf(请输入新的电话\n); scanf(%s, con-arr[find].tel); printf(请输入新的地址\n); scanf(%s, con-arr[find].addr); printf(修改成功!\n); }

用户交互功能与菜单设计当程序运行起来时我们期望有一个菜单能直观地提示用户通过输入什么数字可以调用什么功能所以我们需要设计一个简单菜单void menu() { printf(********************通讯录********************\n); printf(**********************************************\n); printf(*********

增加联系人

删除联系人**********\n); printf(*********

修改联系人

查找联系人**********\n); printf(*********

展示联系人

退出 **********\n); }效果展示我们还需要设计一些交互功能通过do_while和switch语句实现do { menu(); printf(请选择您的操作\n); scanf(%d, op); switch (op) { case 1: AddContact(con); break; case 2: DelContact(con); break; case 3: ModifyContact(con); break; case 4: FindContact(con); break; case 5: ShowContact(con); break; default: break; } } while (op !

;

通讯录各项功能测试

1通讯录初始化测试初始化测试成功通讯录的有效数据个数和容量都初始化为

0.

2通讯录的添加测试

3通讯录的删除和展示测试输入要删除的联系人数据成功提示我们删除成功。

让我们在监视窗口看看size由原来的1减到0说明有效数据个数减少了一位也就是联系人数据被删除了一位。

由于这里我们只插入了一个元素所以只让size-1即可我们就访问不到该联系人信息。

调用从通讯录展示方法ShowContact方法也同样可以直观地看到联系人数据已经被删除了

4通讯录的修改测试再次运行程序在展示之前我们需要先添加两个联系人数据程序提示我们修改成功后在下一次操作中我们需调用展示方法验证修改结果。

通讯录的修改测试也成功通过。

结语以上便是在控制台实现的通讯录交互设计和基本操作方法如果需要在程序退出也能将联系人信息保存下来我们需要配合文件操作方法将联系人信息写到文件中真正地保存下来。

文章到这里就结束了。

代码和文章可能存在纰漏欢迎批评、指正和交流。

共同进步完整代码仓库code_for_study: 学习代码

密挑18-密挑应用

百度百家号客服电话人工服务

123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123