基于动态顺序表实现通讯录 C语⾔基础要求:结构体、动态内存管理、顺序表、⽂件操作
1、功能要求
1)⾄少能够存储100个⼈的通讯信息
2)能够保存⽤⼾信息:名字、性别、年龄、电话、地址等
3)增加联系⼈信息
4)删除指定联系⼈
5)查找制定联系⼈
6)修改指定联系⼈
7)显⽰联系⼈信息


处理方法:


报错:

处理方法:

报错:

处理方法:
头文件最上方加#pragma once
contact.h
- #pragma once
- #define _CRT_SECURE_NO_WARNINGS
- //创建保存联系人数据的结构
- #define NAME_MAX 100
- #define SEX_MAX 100
- #define TEL_MAX 100
- #define ADDR_MAX 100
-
- struct ContactInfo
- {
- char name[NAME_MAX];//使用定长数组还是动态数组?
- char sex[SEX_MAX];//字符数组数组名即为数组首元素地址
- int age;
- char tel[TEL_MAX];
- char addr[ADDR_MAX];
- };
- typedef struct ContactInfo CInfo;
- //通讯表的底层是通过顺序表来实现的
- typedef struct SeqList contact;
- //通讯录的初始化和销毁
- void ContactInit(contact* pcon);//
- void ContactDistory(contact* pcon);
- //添加联系人
- void ContactAdd(contact* pcon);
- int FindByName(contact* pcon, char* name);
- //删除联系人
- void ContactDel(contact* pcon);
- //修改联系人
- void ContactModify(contact* pcon);
- //查看联系人
- void ContactShow(contact* pcon);
- //查找联系人
- void ContactFind(contact* pcon);
Seqlist.h
- #define _CRT_SECURE_NO_WARNINGS
- #include
- #include
- #include
- #include
- #include"Contact.h"
- //typedef int SLDataType;
- typedef struct ContactInfo SLDataType;//更改数据类型为通讯录数据类型
- typedef struct SeqList
- {
- SLDataType* a;
- int size;//顺序表中有效的数据格式
- int capacity;//顺序表当前的空间大小
- }SL;
- //typedef struct SeqList SL(即为)
- //对顺序表进行初始化
- void SLInit(SL* ps);
- //对顺序表进行销毁
- void SLDestory(SL* ps);
- //尾部插入
- void SLPushBack(SL* ps, SLDataType x);
- //头部插入
- void SLPushFront(SL* ps, SLDataType x);
- //尾部删除
- void SLPopBack(SL* ps);
- //头部删除
- void SLPopFront(SL* ps);
- //打印
- void SLPrint(SL* ps);
- //判断顺序表是否位空
- bool SLIsEmpty(SL* ps);
- //在任意位置插入删除
- //在指定位置之前插入数据
- void SLInsert(SL* ps, int pos, SLDataType x);
- //删除指定位置的数据
- void SLErase(SL* ps, int pos);
- bool SLFind(SL* ps, SLDataType x);
- //判断空间是否足够,不够则进行扩容
- void SLCheckCapacity(SL* ps);
contact.c
- #define _CRT_SECURE_NO_WARNINGS
- #include"Contact.h"
- #include"SeqList.h"
- //通讯录的初始化和销毁
- void ContactInit(contact* pcon) {
- SLInit(pcon);
- }
- void ContactDistory(contact* pcon) {
- SLDestory(pcon);
- }
- void ContactAdd(contact* pcon) {
- //所有数据都是CInfo里的
- CInfo 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);
- //获取到联系人数据后,其被保存到了结构体info中
- //下一步即为往通讯录顺序表中插入数据
- SLPushBack(pcon, info);
- }
- int FindByName(contact* pcon, char* name) {
- for (int i = 0; i < pcon->size; i++) {
- if (strcmp(pcon->a[i].name, name) == 0) {
- return i;
- }
- }
- return -1;
- }
- //删除联系人
- void ContactDel(contact* pcon) {
- printf("请输入要删除的用户名称:\n");
- char name[NAME_MAX];
- scanf("%s", name);
- int findindex = FindByName(pcon, name);
- if (findindex < 0) {
- printf("要删除的用户不存在!\n");
- return;
- }
- //找到了要删除findindex位置的数据
- SLErase(pcon, findindex);
- }
- //修改联系人
- void ContactModify(contact* pcon) {
- //打印通讯录所有的数据
- //先打印表头文字
- printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");
- for (int i = 0; i < pcon->size; i++) {
- printf("%-4s %-4s %-4d %-4s %-4s\n",
- pcon->a[i].name,
- pcon->a[i].sex,
- pcon->a[i].age,
- pcon->a[i].tel,
- pcon->a[i].addr
- );
- }
- }
- //查看联系人
- void ContactShow(contact* pcon) {
- char name[NAME_MAX];
- printf("请输入要查找的联系人: \n");
- scanf("%s", name);
- //获得通讯录(顺序表)下标的位置
- int find = FindByName(pcon, name);
- if (find < 0) {
- printf("要查找的用户不存在!\n");
- return;
- }
- printf("请输入新的用户名称: \n");
- scanf("%s", pcon->a[find].name);
- printf("请输入新的用户性别: \n");
- scanf("%s", pcon->a[find].sex);
- printf("请输入新的用户年龄: \n");
- scanf("%d", pcon->a[find].age);
- printf("请输入新的用户电话: \n");
- scanf("%s", pcon->a[find].tel);
- printf("请输入新的用户地址: \n");
- scanf("%s", pcon->a[find].addr);
-
- printf("修改成功! \n");
- }
- //查找联系人
- void ContactFind(contact* pcon) {
- char name [NAME_MAX];
- printf("请输入要查找的联系人 \n");
- scanf("%s", name);
- int find = FindByName(pcon, name);
- if(find < 0) {
- printf("该联系人不存在! \n");
- return;
- }
- //打印当前联系人
- printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");
- printf("%-4s %-4s %-4d %-4s %-4s\n",
- pcon->a[find].name,
- pcon->a[find].sex,
- pcon->a[find].age,
- pcon->a[find].tel,
- pcon->a[find].addr
- );
- }
Seqlist.c
- #define _CRT_SECURE_NO_WARNINGS
- #include"SeqList.h"
- void SLInit(SL* ps) {
- ps->a = NULL;
- ps->capacity = ps->size = 0;//也可在初始化时开辟空间
- }
- void SLDestory(SL* ps) {
- if (ps->a) {
- free(ps->a);
- }
- ps->a = NULL;
- ps->capacity = ps->size = 0;
- }
- void SLCheckCapacity(SL* ps) {
- //空间足够直接尾插
- //空间不够则进行扩容
- if (ps->size == ps->capacity) {
- //空间不够则进行扩容(relloc申请失败返回空指针)
- int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
- SLDataType* tmp = (SLDataType*)realloc(ps->a, newCapacity * 2 * sizeof(SLDataType));
- if (tmp == NULL) {
- perror("relloc fail\n");
- return 1;
- }
- ps->a = tmp;
- ps->capacity = newCapacity;
- }
- }
- void SLPushBack(SL* ps, SLDataType x){
- assert(ps != NULL);
-
- //空间足够直接尾插
- //空间不够则进行扩容(relloc申请失败返回空指针)
- SLCheckCapacity(ps);
- //直接插入数据
- ps->a[ps->size] = x;//ps->a[ps->size++] = x;
- ps->size++;
- }
- void SLPushFront(SL* ps, SLDataType x) {
- assert(ps);
- //判断空间是否足够不够则扩容
- SLCheckCapacity(ps);
- for (size_t i = ps->size; i > 0; i--) {
- ps->a[i] = ps->a[i - 1];
- }
- ps->a[0] = x;
- ps->size++;
- }
- void SLPopBack(SL* ps) {
- assert(ps);
- assert(!SLIsEmpty(ps));//assert(ps->size)也可以
- //ps->a[ps->size - 1] = 0;//(可有可无)
- ps->size--;//size最初为0,为0则不能减减
- }
- void SLPopFront(SL* ps, SLDataType x) {
- assert(ps);
- assert(!SLIsEmpty(ps));//进行判空操作,不为空才能继续
- //让后面数据往前挪一位
- for (size_t i = 0; i < ps->size-1; i++) {//size_t为无符号整形
- //最后一次进来i为ps->size-2
- ps->a[i] = ps->a[i + 1];
- }
- ps->size--;
- }
- void SLPrint(SL* ps) {
- for (size_t i = 0; i < ps->size; i++) {
- printf("%d ", ps->a[i]);
- }
- printf("\n");
- }
- bool SLIsEmpty(SL* ps) {
- assert(ps);
- return ps->size == 0;//当前数据表有效数据位0,则当前数据表为空
- }
- //在指定位置之前插入数据
- void SLInsert(SL* ps, int pos, SLDataType x) {
- assert(ps);
- //对pos加以限制
- assert(pos >= 0 && pos <= ps->size);
- //扩容
- SLCheckCapacity(ps);
- //把pos位置及以后的数据往后挪动一位
- //循环里i的初始值可以为size或size-1k,但不同的初始值对应不同的结束条件
- /*for (size_t i = ps->size; i > pos; i--) {
- ps->a[i] = ps->a[i - 1];
- }*/
- for (size_t i = ps->size-1; i > pos-1; i--) {
- ps->a[i+1] = ps->a[i];
- }
- ps->a[pos] = x;
- ps->size++;
- }
- //删除指定位置的数据
- void SLErase(SL* ps, int pos) {
- assert(ps);
- assert(!SLIsEmpty(ps));//进行判空操作,不为空才能继续
- //对pos加以限制
- assert(pos >= 0 && pos <= ps->size);
- for (int i = pos; i < ps->size - 1; i++) {
- //最后一次进来的i的数据为ps->size - 2
- ps->a[i] = ps->a[i + 1];
- }
- ps->size--;
- }
- //bool SLFind(SL* ps, SLDataType x) {
- // assert(ps);
- // for (int i = 0; i < ps->size; i++) {
- // if (ps->a[i] == x) {
- // 找到了
- // return true;
- // }
- // }
- // return false;
- //}
test.c
- #define _CRT_SECURE_NO_WARNINGS
- #include"SeqList.h"
- #include"Contact.h"
- //void SLtest() {
- // SL sl;
- // SLInit(&sl);
- // //尾部插入
- // SLPushBack(&sl, 1);
- // SLPushBack(&sl, 2);
- // SLPushBack(&sl, 3);
- // SLPushBack(&sl, 4);
- // SLPrint(&sl);
- // //头部插入
- // SLPushFront(&sl, 5);
- // SLPushFront(&sl, 6);
- // SLPushFront(&sl, 7);
- // SLPrint(&sl);
- // SLPopBack(&sl);
- // SLPrint(&sl);
- // SLPopBack(&sl);
- // SLPrint(&sl);
- // SLDestory(&sl);
- //}
- //void SLtest02() {
- // SL sl;
- // SLInit(&sl);
- // //尾部插入
- // SLPushBack(&sl, 1);
- // SLPushBack(&sl, 2);
- // SLPushBack(&sl, 3);
- // SLPushBack(&sl, 4);
- // SLPrint(&sl);
- // 头删
- // //SLPopFront(&sl);
- // //SLPrint(&sl);
- // //SLPopFront(&sl);
- // //SLPrint(&sl);
- // //SLDestory(&sl);
- // //在指定位置之前插入数据
- // /*SLInsert(&sl, 1, 11);
- // SLPrint(&sl);
- // SLDestory(&sl);*/
- // 删除指定位置的数据
- // //SLErase(&sl, 0);
- // //SLPrint(&sl);
- // //SLErase(&sl, sl.size-1);
- // //SLPrint(&sl);
- // //
- // bool findRet=SLFind(&sl, 3);
- // if (findRet) {
- // printf("找到了\n");
- // }
- // else {
- // printf("没有找到!\n");
- // }
- // SLDestory(&sl);
-
-
- //void contact01() {
- // contact con;
- // ContactInit(&con);
- // //往通讯录中插入数据
- // ContactAdd(&con);
- // ContactDistory(&con);
- // }
- //}
- void menu()
- {
- printf("***************通讯录**************\n");
- printf("****1> 添加联系人 2>删除联系人*****\n");
- printf("****3> 修改联系人 4>查找联系人*****\n");
- printf("****5> 查看通讯录 0>退出 *****\n");
- printf("**********************************\n");
- }
- int main() {
- //SLtest();
- //SLtest02();
- /*contact01();*/
- contact con;
- int op = -1;
- ContactInit(&con);
- do {
- menu();
- printf("请输入您的操作:> \n");
- scanf("%d", &op);
- switch (op) {
- case 1:
- ContactAdd(&con);
- break;
- case 2:
- ContactDel(&con);
- break;
- case 3:
- ContactModify(&con);
- break;
- case 4:
- ContactFind(&con);
- break;
- case 5:
- ContactShow(&con);
- break;
- case 0:
- printf("~BYE~\n");
- break;
- }
- } while (op != 0);
- ContactDistory(&con);
- return 0;
- }