1.代码展示
1.1 test.c
#define _CRT_SECURE_NO_WARNINGS
#include"SeqList.h"
#include"Contact.h"
void TsetContact01()
{
Contact con;
ContactInit(&con);
ContactAdd(&con);
ContactDestroy(&con);
}
void menu()
{
printf("*************通 讯 录*************\n");
printf("********1.添加 2.删除***********\n");
printf("********3.修改 4.展示***********\n");
printf("********5.查找 0.退出***********\n");
printf("**********************************\n");
}
int main()
{
//SLTest01();
//SLTest02();
//TsetContact01();
Contact con;
ContactInit(&con);
int op = -1;
do {
menu();
printf("请选择您的操作:");
scanf("%d", &op);
switch(op)
{
case 1:
ContactAdd(&con);
break;
case 2:
ContactDel(&con);
break;
case 3:
ContactModify(&con);
break;
case 4:
ContactShow(&con);
break;
case 5:
ContactFind(&con);
break;
case 0:
printf("退出通讯录!\n");
exit(0);
break;
default:
printf("请输入正确的数字:\n");
break;
}
} while (op != 0);
ContactDestroy(&con);
return 0;
}
1.2 Contact.c
#include"Contact.h"
#include"SeqList.h"
//通讯录的初始化
void ContactInit(Contact* con)
{
SLInit(con);
}
//销毁
void ContactDestroy(Contact* con)
{
SLDestroy(&con);
}
int FindByname(Contact * con,char name[])
{
for(int i = 0; i < con->size; i++)
{
if (strcmp(con->arr[i].name, name))
{
return i;
}
}
return -1;
}
//添加
void ContactAdd(Contact* con)
{
peoInfo info;
printf("请输入联系人的姓名:");
scanf("%s", info.name);
printf("请输入联系人的性别:");
scanf("%s", info.gender);
printf("请输入联系人的年龄:");
scanf("%d", &info.age);
printf("请输入联系人的电话:");
scanf("%s", info.tel);
printf("请输入联系人的住址:");
scanf("%s", info.add);
//插入数据
SeqListPushBack(con, info);
}
//删除
void ContactDel(Contact* con)
{
char name[NAME_MAX];
printf("请输入要删除的联系人:");
scanf("%s", name);
int find = FindByname(con, name);
if (find < 0)
{
printf("要删除的联系人不存在!");
return;
}
SLErase(con, find);
printf("删除成功!\n");
}
//展示
void ContactShow(Contact* con)
{
printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");
for (int i = 0; i < con->size; i++)
{
printf("%3s %4s %4d %4s %4s\n",
con->arr[i].name,
con->arr[i].gender,
con->arr[i].age,
con->arr[i].tel,
con->arr[i].add
);
}
}
//修改
void ContactModify(Contact* con)
{
char name[NAME_MAX];
printf("请输入要修改的联系人:");
scanf("%s", name);
int find = FindByname(con, name);
if (find < 0)
{
printf("要修改的联系人不存在!\n");
return;
}
printf("请输入新的联系人名:");
scanf("%s", con->arr[find].name);
printf("请输入新的联系人性别:");
scanf("%s", con->arr[find].gender);
printf("请输入新的联系年龄:");
scanf("%d", con->arr[find].age);
printf("请输入新的联系电话:");
scanf("%s", con->arr[find].tel);
printf("请输入新的联系住址:");
scanf("%s", con->arr[find].add);
printf("修改成功!\n");
}
//查找
void ContactFind(Contact* con)
{
char name[NAME_MAX];
printf("请输入要查找的联系人:");
scanf("%s", name);
int find = FindByname(&con, name);
if (find < 0)
{
printf("要查找的联系人不存在!\n");
return;
}
printf("请输入新的联系人名:");
scanf("%s", con->arr[find].name);
printf("请输入新的联系人性别:");
scanf("%s", con->arr[find].gender);
printf("请输入新的联系年龄:");
scanf("%d", con->arr[find].age);
printf("请输入新的联系电话:");
scanf("%s", con->arr[find].tel);
printf("请输入新的联系住址:");
scanf("%s", con->arr[find].add);
}
1.3 Contact.h
#define _CRT_SECURE_NO_WARNINGS
#pragma once
#define NAME_MAX 20
#define GENDER_MAX 20
#define TEL_MAX 20
#define ADD_MAX 100
typedef struct personInfo
{
char name[NAME_MAX];
char gender[GENDER_MAX];
int age;
char tel[TEL_MAX];
char add[ADD_MAX];
}peoInfo;
typedef struct SeqList Contact;
//通讯录的初始化
void ContactInit(Contact* con);
//销毁
void ContactDestroy(Contact* con);
//添加
void ContactAdd(Contact* con);
//删除
void ContactDel(Contact* con);
//修改
void ContactModify(Contact* con);
//查找
void ContactFind(Contact* con);
//展示
void ContactShow(Contact* con);
1.4 SeqList.c
#include"SeqList.h"
void SLInit(SL *ps)
{
ps->arr = NULL;
ps->size = ps->capacity = 0;
}
//顺序表的销毁
void SLDestroy(SL *ps)
{
if (ps->arr) //等价于if(ps->arr != NULL)
{
free(ps->arr);
}
ps->arr = NULL;
ps->size = ps->capacity = 0;
}
//判断函数
void SLCheckCapacity(SL *ps)
{
//插入前判断空间是否充足
if (ps->size == ps->capacity)
{
//申请空间
//三目表达式
int NewCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
SLDataType* tmp = (SLDataType*)realloc(ps->arr, NewCapacity * sizeof(SLDataType));
//申请内存空间
if (tmp == NULL)
{
perror("realloc failed");
exit(1);//空间申请失败,直接退出程序
}
//空间申请成功
ps->arr = tmp;
ps->capacity = NewCapacity;
}
}
void SLPrint(SL s)
{
for (int i = 0; i < s.size; i++)
{
printf("%d ", s.arr[i]);
}
printf("\n");
}
//尾插函数
void SeqListPushBack(SL* ps, SLDataType x)
{
assert(ps);
SLCheckCapacity(ps);
ps->arr[ps->size++] = x;
}
//头插函数
void SeqListPushFront(SL* ps, SLDataType x)
{
assert(ps);
SLCheckCapacity(ps);
//首先将顺序表现有数字后移一位
for (int i = ps->size; i > 0; i--)
{
ps->arr[i] = ps->arr[i - 1];
}
ps->arr[0] = x;
ps->size++;
}
//尾删函数
void SeqListPopBack(SL* ps)
{
assert(ps);
assert(ps->size);
--ps->size;
}
//头删函数
void SeqListPopFront(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, SLDataType x)
{
assert(ps);
assert(pos >= 0 && pos <= ps->size);
//在指定位置之前插入数据
//判断空间大小,不够增容
SLCheckCapacity(ps);
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);
for (int i = pos; i < ps->size - 1; i++)
{
ps->arr[i] = ps->arr[i + 1];
}
ps->size--;
}
//顺序表查找
//void SLFind(SL* ps, SLDataType x)
//{
// assert(ps);
// for (int i = 0; i < ps->size; i++)
// {
// if (ps->arr[i] == x)
// {
// return i;
// }
// }
// //没有找到
// return -1;
//}
1.5 SeqList.h
#define _CRT_SECURE_NO_WARNINGS
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include"Contact.h"
//#define N 100
静态顺序表
//struct SeqList
//{
// int arr[N];
// int size;
//};
//typedef int SLDataType;
typedef peoInfo SLDataType;
//动态顺序表
struct SeqList
{
SLDataType *arr;
int size; //有效数据个数
int capacity; //空间大小
};
typedef struct SeqList SL;
//增删查改等接口函数
void SLInit(SL *ps);
//尾插函数
void SeqListPushBack(SL* ps, SLDataType x);
//头插函数
void SeqListPushFront(SL* ps, SLDataType x);
//尾删函数
void SeqListPopBack(SL* ps);
//头删函数
void SeqListPopFront(SL* ps);
//打印函数
void SLPrint(SL s);
//销毁函数
void SLDestroy(SL* ps);
//指定位置插入函数
void SLInsert(SL* ps, int pos, SLDataType x);
//删除指定位置数据
void SLErase(SL* ps, int pos);
//顺序表查找
void SLFind(SL* ps, SLDataType x);
2.模块详解
2.1 test.c
该源文件只用来做菜单等测试用例的测试,运行后的界面如图所示
2.2 通讯录的初始化
//通讯录的初始化
void ContactInit(Contact* con)
{
SLInit(con);
}
void SLInit(SL *ps)
{
ps->arr = NULL;
ps->size = ps->capacity = 0;
}
初始化实质上就是将第一个数组置为 NULL 空指针,将其余变量初始化为 0
2.3 销毁
//销毁
void ContactDestroy(Contact* con)
{
SLDestroy(&con);
}
//顺序表的销毁
void SLDestroy(SL *ps)
{
if (ps->arr) //等价于if(ps->arr != NULL)
{
free(ps->arr);
}
ps->arr = NULL;
ps->size = ps->capacity = 0;
}
销毁就是首先判断是否为空,若不为空则释放当前的空间,然后进行初始化
2.4 添加
//添加
void ContactAdd(Contact* con)
{
peoInfo info;
printf("请输入联系人的姓名:");
scanf("%s", info.name);
printf("请输入联系人的性别:");
scanf("%s", info.gender);
printf("请输入联系人的年龄:");
scanf("%d", &info.age);
printf("请输入联系人的电话:");
scanf("%s", info.tel);
printf("请输入联系人的住址:");
scanf("%s", info.add);
//插入数据
SeqListPushBack(con, info);
}
//判断函数
void SLCheckCapacity(SL *ps)
{
//插入前判断空间是否充足
if (ps->size == ps->capacity)
{
//申请空间
//三目表达式
int NewCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
SLDataType* tmp = (SLDataType*)realloc(ps->arr, NewCapacity * sizeof(SLDataType));
//申请内存空间
if (tmp == NULL)
{
perror("realloc failed");
exit(1);//空间申请失败,直接退出程序
}
//空间申请成功
ps->arr = tmp;
ps->capacity = NewCapacity;
}
}
//尾插函数
void SeqListPushBack(SL* ps, SLDataType x)
{
assert(ps);
SLCheckCapacity(ps);
ps->arr[ps->size++] = x;
}
我们这里用到的是尾插,即判断是否满足插入条件,满足则直接插入数据,反之报错,用断言assert来做限制。
2.5 修改
//修改
void ContactModify(Contact* con)
{
char name[NAME_MAX];
printf("请输入要修改的联系人:");
scanf("%s", name);
int find = FindByname(con, name);
if (find < 0)
{
printf("要修改的联系人不存在!\n");
return;
}
printf("请输入新的联系人名:");
scanf("%s", con->arr[find].name);
printf("请输入新的联系人性别:");
scanf("%s", con->arr[find].gender);
printf("请输入新的联系年龄:");
scanf("%d", con->arr[find].age);
printf("请输入新的联系电话:");
scanf("%s", con->arr[find].tel);
printf("请输入新的联系住址:");
scanf("%s", con->arr[find].add);
printf("修改成功!\n");
}
int FindByname(Contact * con,char name[])
{
for(int i = 0; i < con->size; i++)
{
if (strcmp(con->arr[i].name, name))
{
return i;
}
}
return -1;
}
这里先使用 FindByName 函数判断所查联系人是否存在,若存在则返回 i,反之返回 -1。然后将返回值作为修改条件成立与否的判断,之后就可以进行数据的修改。
2.6 删除
//删除
void ContactDel(Contact* con)
{
char name[NAME_MAX];
printf("请输入要删除的联系人:");
scanf("%s", name);
int find = FindByname(con, name);
if (find < 0)
{
printf("要删除的联系人不存在!");
return;
}
SLErase(con, find);
printf("删除成功!\n");
}
//删除指定位置数据
void SLErase(SL* ps, int pos)
{
assert(ps);
assert(pos >= 0 && pos < ps->size);
for (int i = pos; i < ps->size - 1; i++)
{
ps->arr[i] = ps->arr[i + 1];
}
ps->size--;
}
先通过 FindByName 函数判断数据是否存在,随即使用 SLErase 删除函数删除数据,底层逻辑是判断所删除数据是否在数组的头尾之间,若在那么直接将下一个数据覆盖到当前位置,即完成一个删除动作。
2.7 展示
//展示
void ContactShow(Contact* con)
{
printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");
for (int i = 0; i < con->size; i++)
{
printf("%3s %4s %4d %4s %4s\n",
con->arr[i].name,
con->arr[i].gender,
con->arr[i].age,
con->arr[i].tel,
con->arr[i].add
);
}
}
展示就是把数组中存储的数据依次打印出来即可。