正文开始
前言
书接上文, 我们已经初步了解了线性表, 顺序表其实就是在数组的基础上增加了一些特有的功能, 那么顺序表有哪些应用呢? 下面我们一起使用顺序表实现通讯录的功能.
博客主页:酷酷学!!!
基于上篇的讲解, 我们继续来给顺序表添加以下三个功能
//在指定位置前插入元素
void SLInsert(SL* sp,int pos,DataType x);
//删除指定位置的元素
void SLErase(SL* sp, int pos);
//查找元素所在位置
int SLFind(SL* sp, DataType x);
上篇我们已经了解了顺序表基础的运用, 基于此我们让顺序表的功能更完善
实现代码如下:
void SLInsert(SL* sp, int pos, DataType x)
{
assert(sp);
assert(pos >= 0 && pos <= sp->size);
SLCheckcapacity(sp);
for (int i = sp->size; i>pos; i--)
{
sp->arr[i] = sp->arr[i - 1];//最后一次arr[pos+1] = arr[pos]
}
sp->arr[pos] = x;
sp->size++;
}
void SLErase(SL* sp, int pos)
{
assert(sp);
assert(pos >= 0 && pos < sp->size);
for (int i = pos; i<sp->size-1; i++)
{
sp->arr[i] = sp->arr[i + 1];//最后一次arr[size-2] = arr[size-1]
}
sp->size--;
}
int SLFind(SL* sp, DataType x)
{
assert(sp);
for (int i = 0; i < sp->size; i++)
{
if (x == sp->arr[i])
{
return i;
}
}
return -1;
}
上面三个函数分别对应以上三个功能, 其中查找函数只能运用于整形, 不适用于通讯录查找, 所以在实现通讯录功能时我们可以注释掉, 下面将进入本篇正题: 实现通讯录功能
一. 通讯录功能要求
1)至少少能够存储100个⼈的通讯信息
2)能够保存用户信息:名字、性别、年龄、电话、地址等
3)增加联系人信息
4)删除指定联系人
5)查找制定联系人
6)修改指定联系人
7)显示联系⼈信息
二. 实现方法
第一步:
基于顺序表我们在此之上创建两个文件, 分别为Contact.h和Contact.c用来存放通讯录的声明和方法实现
第二步:
#pragma once
#define MAX_NAME 20
#define MAX_GENDER 10
#define MAX_TEL 10
#define MAX_ADDRESS 100
typedef struct personInfo
{
char name[MAX_NAME];
char gender[MAX_GENDER];
int age;
char tel[MAX_TEL];
char address[MAX_ADDRESS];
}peoInfo;
typedef struct SeqList Contact;//需要先前置声明,才能改名字
在Contact.h 头文件中声明一个通讯录的类型, 并且将顺序表改名字为Contact,这样做的目的是为了格式化统一, 但是修改前不能使用 typedef SL Contact 来修改, 因为不能重复包含头文件, 所以我们可以使用前置声明.
第三步:
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include"Contact.h"
typedef peoInfo DataType;
typedef struct SeqList
{
DataType* arr;
int size;
int capacity;
}SL;
更改SeqList.h 头文件中的DataType类型, 使其存储的每一个元素为通讯录, 并且包含通讯录的头文件, 这里可以直接使用 typedef peoInfo SeqList 直接修改名字, 就是因为已经包含了通讯录的头文件
第四步:
实现通讯录的各种方法
现在通讯录Contact.h 文件中声明方法, 接着在Contact.c文件中进行实现
Contact.h文件
//通讯录的初始化
void ContactInit(Contact* con);
//通讯录的销毁
void ContactDestory(Contact* con);
//通讯录的插入
void ContactAdd(Contact* con);
//通讯录的删除
void ContactDel(Contact* con);
//展示通讯录
void ContactShow(Contact* con);
//通讯录的修改
void ContactModify(Contact* con);
//通讯录查找
void ContactFind(Contact* con);
以上就是我们需要完成的所以函数的声明
Contact.c文件
#include"SeqList.h"
#include"Contact.h"
void ContactInit(Contact* con)
{
SLInit(con);//这里其实就是顺序表的初始化
}
void ContactDestory(Contact* con)
{
SLDestory(con);//这里也是顺序表
}
void ContactAdd(Contact* con)
{
peoInfo info;
printf("请输入姓名\n");
scanf("%s", info.name);
printf("请输入性别\n");
scanf("%s", info.gender);
printf("请输入年龄\n");
scanf("%d",&info.age);
printf("请输入电话\n");
scanf("%s", info.tel);
printf("请输入地址\n");
scanf("%s", info.address);
SLPushBack(con,info);//还是使用顺序表的方法
}
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 ContactDel(Contact* con)
{
char name[MAX_NAME];
printf("请输入要删除的联系人姓名\n");
scanf("%s", name);
int find = findByName(con, name);
if (find < 0)
{
printf("要删除的联系人不存在\n");
return;
}
SLErase(con, find);//还是顺序表
printf("删除成功\n");
}
void ContactShow(Contact* con)
{
printf("%-5s %-5s %-5s %-5s %-5s\n", "姓名", "性别", "年龄", "电话", "地址");
for (int i = 0; i < con->size; i++)
{
printf("%-5s %-5s %-5d %-5s %-5s\n",
con->arr[i].name,
con->arr[i].gender,
con->arr[i].age,
con->arr[i].tel,
con->arr[i].address);
}
}
void ContactModify(Contact* con)
{
char name[MAX_NAME];
printf("请输入要修改的用户姓名\n");
scanf("%s", name);
int find = findByName(con, name);
if (find < 0)
{
printf("要修改的联系人不存在\n");
}
printf("请输入要修改的姓名\n");
scanf("%s", con->arr[find].name);
printf("请输入要修改的性别\n");
scanf("%s", con->arr[find].gender);
printf("请输入要修改的年龄\n");
scanf("%d", &con->arr[find].age);
printf("请输入要修改的电话\n");
scanf("%s", con->arr[find].tel);
printf("请输入要修改的地址\n");
scanf("%s", con->arr[find].address);
printf("修改成功\n");
}
void ContactFind(Contact* con)
{
char name[MAX_NAME];
printf("请输入要查找的姓名\n");
scanf("%s", name);
int find = findByName(con, name);
if (find < 0)
{
printf("要查找的联系人不存在\n");
return;
}
printf("%-5s %-5s %-5s %-5s %-5s\n", "姓名", "性别", "年龄", "电话", "地址");
for (int i = 0; i < con->size; i++)
{
printf("%-5s %-5s %-5d %-5s %-5s\n",
con->arr[find].name,
con->arr[find].gender,
con->arr[find].age,
con->arr[find].tel,
con->arr[find].address);
}
}
以上为实习功能的Contact.c文件,其中我们需要包含SeqList.h文件 , 因为要使用到顺序表的方法, 并且包含Contact.h文件, 需要使用里面的声明的结构体. 代码解释请看注释, 如有其他疑惑, 欢迎评论区或者私信留言!!
三. 代码汇总
SeqList.h
#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include"Contact.h"
typedef peoInfo DataType;
typedef struct SeqList
{
DataType* arr;
int size;
int capacity;
}SL;
void SLInit(SL* sp);
void SLDestory(SL* sp);
//判空
void SLCheckcapacity(SL* sp);
//打印
void SLPrint(SL sp);
//尾插
void SLPushBack(SL* sp, DataType x);
//头插
void SLPushFront(SL* sp, DataType x);
//尾删
void SLPopBack(SL* sp);
//头删
void SLPopFront(SL* sp);
//在指定位置前插入元素
void SLInsert(SL* sp,int pos,DataType x);
//删除指定位置的元素
void SLErase(SL* sp, int pos);
//查找元素所在位置
int SLFind(SL* sp, DataType x);
SeqList.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"
//初始化
void SLInit(SL* sp)
{
assert(sp);
sp->arr = NULL;
sp->capacity = sp->size = 0;
}
//销毁
void SLDestory(SL* sp)
{
assert(sp);
if (sp->arr)
{
free(sp->arr);
}
sp->arr = NULL;
sp->capacity = sp->size = 0;
}
//打印
//void SLPrint(SL sp)
//{
// for (int i = 0; i < sp.size; i++)
// {
// printf("%d ", sp.arr[i]);
// }
// printf("\n");
//}
//判空
void SLCheckcapacity(SL* sp)
{
if (sp->size == sp->capacity)
{
int Newcapacity = sp->capacity == 0 ? 2 : sp->capacity * 2;
DataType* tmp = (DataType*)realloc(sp->arr, Newcapacity * sizeof(DataType));
if (tmp == NULL)
{
perror("realloc fail");
}
sp->arr = tmp;
tmp = NULL;
sp->capacity = Newcapacity;
}
}
//尾插
void SLPushBack(SL* sp, DataType x)
{
assert(sp);
SLCheckcapacity(sp);
sp->arr[sp->size++] = x;
}
//头插
void SLPushFront(SL* sp, DataType x)
{
assert(sp);
SLCheckcapacity(sp);
for (int i = sp->size; i>0; i--)
{
sp->arr[i] = sp->arr[i - 1];//最后一次arr[1] = arr[0]
}
sp->arr[0] = x;
sp->size++;
}
//尾删
void SLPopBack(SL* sp)
{
assert(sp);
sp->size--;
}
//头删
void SLPopFront(SL* sp)
{
assert(sp);
for (int i = 0; i<sp->size-1; i++)
{
sp->arr[i] = sp->arr[i + 1]; //最后一次arr[size-2] = arr[size-1]
}
sp->size--;
}
void SLInsert(SL* sp, int pos, DataType x)
{
assert(sp);
assert(pos >= 0 && pos <= sp->size);
SLCheckcapacity(sp);
for (int i = sp->size; i>pos; i--)
{
sp->arr[i] = sp->arr[i - 1];//最后一次arr[pos+1] = arr[pos]
}
sp->arr[pos] = x;
sp->size++;
}
void SLErase(SL* sp, int pos)
{
assert(sp);
assert(pos >= 0 && pos < sp->size);
for (int i = pos; i<sp->size-1; i++)
{
sp->arr[i] = sp->arr[i + 1];//最后一次arr[size-2] = arr[size-1]
}
sp->size--;
}
//int SLFind(SL* sp, DataType x)
//{
// assert(sp);
// for (int i = 0; i < sp->size; i++)
// {
// if (x == sp->arr[i])
// {
// return i;
// }
// }
// return -1;
//}
Contact.h
#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#define MAX_NAME 20
#define MAX_GENDER 10
#define MAX_TEL 10
#define MAX_ADDRESS 100
typedef struct personInfo
{
char name[MAX_NAME];
char gender[MAX_GENDER];
int age;
char tel[MAX_TEL];
char address[MAX_ADDRESS];
}peoInfo;
typedef struct SeqList Contact;//需要先前置声明,才能改名字
//通讯录的初始化
void ContactInit(Contact* con);
//通讯录的销毁
void ContactDestory(Contact* con);
//通讯录的插入
void ContactAdd(Contact* con);
//通讯录的删除
void ContactDel(Contact* con);
//展示通讯录
void ContactShow(Contact* con);
//通讯录的修改
void ContactModify(Contact* con);
//通讯录查找
void ContactFind(Contact* con);
Contact.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"
#include"Contact.h"
void ContactInit(Contact* con)
{
SLInit(con);
}
void ContactDestory(Contact* con)
{
SLDestory(con);
}
void ContactAdd(Contact* con)
{
peoInfo info;
printf("请输入姓名\n");
scanf("%s", info.name);
printf("请输入性别\n");
scanf("%s", info.gender);
printf("请输入年龄\n");
scanf("%d",&info.age);
printf("请输入电话\n");
scanf("%s", info.tel);
printf("请输入地址\n");
scanf("%s", info.address);
SLPushBack(con,info);
}
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 ContactDel(Contact* con)
{
char name[MAX_NAME];
printf("请输入要删除的联系人姓名\n");
scanf("%s", name);
int find = findByName(con, name);
if (find < 0)
{
printf("要删除的联系人不存在\n");
return;
}
SLErase(con, find);
printf("删除成功\n");
}
void ContactShow(Contact* con)
{
printf("%-5s %-5s %-5s %-5s %-5s\n", "姓名", "性别", "年龄", "电话", "地址");
for (int i = 0; i < con->size; i++)
{
printf("%-5s %-5s %-5d %-5s %-5s\n",
con->arr[i].name,
con->arr[i].gender,
con->arr[i].age,
con->arr[i].tel,
con->arr[i].address);
}
}
void ContactModify(Contact* con)
{
char name[MAX_NAME];
printf("请输入要修改的用户姓名\n");
scanf("%s", name);
int find = findByName(con, name);
if (find < 0)
{
printf("要修改的联系人不存在\n");
}
printf("请输入要修改的姓名\n");
scanf("%s", con->arr[find].name);
printf("请输入要修改的性别\n");
scanf("%s", con->arr[find].gender);
printf("请输入要修改的年龄\n");
scanf("%d", &con->arr[find].age);
printf("请输入要修改的电话\n");
scanf("%s", con->arr[find].tel);
printf("请输入要修改的地址\n");
scanf("%s", con->arr[find].address);
printf("修改成功\n");
}
void ContactFind(Contact* con)
{
char name[MAX_NAME];
printf("请输入要查找的姓名\n");
scanf("%s", name);
int find = findByName(con, name);
if (find < 0)
{
printf("要查找的联系人不存在\n");
return;
}
printf("%-5s %-5s %-5s %-5s %-5s\n", "姓名", "性别", "年龄", "电话", "地址");
for (int i = 0; i < con->size; i++)
{
printf("%-5s %-5s %-5d %-5s %-5s\n",
con->arr[find].name,
con->arr[find].gender,
con->arr[find].age,
con->arr[find].tel,
con->arr[find].address);
}
}
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"
//void test1(SL* ps)
//{
// SLPushBack(ps, 10);
// SLPushBack(ps, 20);
// SLPushBack(ps, 30);
// SLPrint(*ps);
// SLPushFront(ps, 40);
// SLPushFront(ps, 50);
// SLPrint(*ps);
// SLPopBack(ps);
// SLPopBack(ps);
// SLPrint(*ps);
// SLPopFront(ps);
// SLPrint(*ps);
// SLInsert(ps, 0, 99);
// SLPrint(*ps);
// SLInsert(ps, ps->size, 100);
// SLPrint(*ps);
// SLInsert(ps, 2, 50);
// SLPrint(*ps);
// SLErase(ps, 0);
// SLPrint(*ps);
// SLErase(ps, ps->size - 1);
// SLPrint(*ps);
// printf("%d\n", SLFind(ps, 50));
//
//}
//int main()
//{
// SL s;
// SLInit(&s);
// test1(&s);
// SLDestory(&s);
// return 0;
//}
//void Contest1()
//{
// Contact con;
// ContactInit(&con);
// ContactAdd(&con);
// ContactAdd(&con);
// ContactShow(&con);
//
// ContactDel(&con);
// ContactShow(&con);
//
// ContactDestory(&con);
//}
void meun()
{
printf("********************通讯录*********************\n");
printf("********1.增加联系人 2.删除联系*************\n");
printf("********3.修改联系人 4.查找联系人***********\n");
printf("********5.展示联系人 0.退出*****************\n");
printf("***********************************************\n");
}
int main()
{
//Contest1();
int op = -1;
Contact con;
ContactInit(&con);
do{
meun();
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("退出通讯录......\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (op != 0);
ContactDestory(&con);
return 0;
}
四. 效果展示
界面:
增加联系人并且查看
删除联系人并且查看
修改查找
总结
只要掌握了顺序表的实现方法, 通讯录就是在顺序表的基础上套个壳子, 结合文件操作我们也可以把数据存储起来.
完