- 前言
- 1. 基于动态顺序表实现通讯录
- 1.1 通讯录功能
- 1.2 代码实现
- 1.2.1 SeqList.h
- 1.2.2 SeqList.c
- 1.2.3 Contact.h
- 1.2.4 Contact.c
- 1.2.5 test.c
- 1.3 控制台测试
- 1.3.1 添加联系人
- 1.3.2 删除联系人
- 1.3.3 修改联系人
- 1.3.4 查找联系人
- 1.3.5 清空通讯录
- 1.3.6 通讯录读档和存档
- 2. 好题测验
- 2.1 好题展示
- 2.2 答案解析
- 结语
上期回顾: 【数据结构|C语言版】顺序表
个人主页: C_GUIQU
前言
各位小伙伴大家好!上期小编给大家讲解了数据结构中的顺序表,接下来讲讲顺序表该如何应用。
1. 基于动态顺序表实现通讯录
1.1 通讯录功能
(1)能够保存联系人的姓名、年龄、性别、电话、住址
(2)添加联系人信息
(3)删除联系人信息
(4)修改联系人信息
(5)查找联系人信息
(6)查看通讯录中所有联系人信息
(7)清空通讯录
(8)每次加载通讯录时自动载入历史通讯录,退出通讯录后自动保存通讯录信息
1.2 代码实现
1.2.1 SeqList.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <Windows.h>
#include "Contact.h"
typedef Info SLDataType; //顺序表元素种类为存放个人信息的结构体
typedef struct SeqList
{
SLDataType* a;
size_t size;
size_t capicity;
} SeqList;
// 顺序表初始化
void SeqListInit(SeqList* psl);
// 检查空间,如果满了,进行增容
void CheckCapacity(SeqList* psl);
// 顺序表尾插
void SeqListPushBack(SeqList* psl, SLDataType x);
// 顺序表删除pos位置的值
void SeqListErase(SeqList* psl, size_t pos);
// 顺序表销毁
void SeqListDestory(SeqList* psl);
1.2.2 SeqList.c
#include "SeqList.h"
void SeqListDestory(SeqList* psl)
{
assert(psl);
free(psl->a);
psl->a = NULL;
psl->capicity = 0;
psl->size = 0;
}
void SeqListInit(SeqList* psl)
{
assert(psl);
psl->a = (SLDataType*)malloc(sizeof(SLDataType) * 4);
if (psl->a == NULL)
{
perror("malloc fail");
return;
}
psl->size = 0;
psl->capicity = 4;
}
void CheckCapacity(SeqList* psl)
{
assert(psl);
if (psl->size == psl->capicity)
{
SLDataType* tmp = (SLDataType*)realloc(psl->a, sizeof(SLDataType) * psl->capicity * 2);
if (tmp == NULL)
{
perror("realloc fail");
return;
}
psl->a = tmp;
psl->capicity *= 2;
}
}
void SeqListPushBack(SeqList* psl, SLDataType x)
{
assert(psl);
CheckCapacity(psl);
psl->a[psl->size++] = x;
}
void SeqListErase(SeqList* psl, size_t pos)
{
assert(psl);
assert(0 <= pos && pos < psl->size);
while (pos < psl->size - 1)
{
psl->a[pos] = psl->a[pos + 1];
pos++;
}
psl->size--;
}
1.2.3 Contact.h
#pragma once
#define NAME_MAX 100
#define GENDER_MAX 10
#define TEL_MAX 11
#define ADDR_MAX 100
struct SqeList;
//因为这里不能声明SeqList.h,不然会造成嵌套声明,所以就单独声明一下顺序表
typedef struct SeqList contact;
//要实现的是通讯录,所以得把顺序表换个名,但换汤不换药
typedef struct PersonInfo
{
char name[NAME_MAX]; //姓名
int age; //年龄
char gender[GENDER_MAX]; //性别
char telephone[TEL_MAX]; //电话
char address[ADDR_MAX]; //住址
}Info;
void InitContact(contact* pcon);//初始化通讯录
void DestoryContact(contact* pcon);//销毁通讯录
int FindByName(contact* pcon, char* name);//通过姓名查找联系人
void AddContact(contact* pcon);//添加联系人
void DelContact(contact* pcon);//删除联系人
void ModifyContact(contact* pcon);//修改联系人信息
void FindContact(contact* pcon);//查找联系人
void ShowContact(contact* pcon);//展示联系人列表
void ClearContact(contact* pcon);//清空通讯录
void SaveContact(contact* pcon);//保存通讯录
void LoadContact(contact* pcon);//载入历史通讯录
1.2.4 Contact.c
#include "SeqList.h"
void InitContact(contact* pcon)//初始化通讯录
{
SeqListInit(pcon);
}
void DestoryContact(contact* pcon)//销毁通讯录
{
SeqListDestory(pcon);
}
int FindByName(contact* pcon, char* name)//通过姓名查找联系人
{
for (size_t i = 0; i < pcon->size; i++)
{
if (strcmp(name, pcon->a[i].name) == 0)
{
return i;
}
}
return -1;
}
void AddContact(contact* pcon)//添加联系人
{
CheckCapacity(pcon);
printf("请输入姓名:\n");
scanf("%s", pcon->a[pcon->size].name);
printf("请输入年龄:\n");
scanf("%d", &(pcon->a[pcon->size].age));
printf("请输入性别:\n");
scanf("%s", pcon->a[pcon->size].gender);
printf("请输入电话:\n");
scanf("%s", pcon->a[pcon->size].telephone);
printf("请输入住址:\n");
scanf("%s", pcon->a[pcon->size].address);
pcon->size++;
system("cls");
printf("添加成功!\n");
}
void DelContact(contact* pcon)//删除联系人
{
char name[100];
printf("请输入要删除的联系人:\n");
scanf("%s", name);
int index = FindByName(pcon, name);
if (index == -1)
{
printf("要删除的用户不存在!\n");
return;
}
SeqListErase(pcon, index);
system("cls");
printf("删除成功!\n");
}
void ModifyContact(contact* pcon)//修改联系人信息
{
char name[100];
printf("请输入要修改的联系人:\n");
scanf("%s", name);
int index = FindByName(pcon, name);
if (index == -1)
{
printf("要修改的用户不存在!\n");
return;
}
printf("请输入修改后的姓名:\n");
scanf("%s", pcon->a[index].name);
printf("请输入修改后的年龄:\n");
scanf("%d", &(pcon->a[index].age));
printf("请输入修改后的性别:\n");
scanf("%s", pcon->a[index].gender);
printf("请输入修改后的电话:\n");
scanf("%s", pcon->a[index].telephone);
printf("请输入修改后的住址:\n");
scanf("%s", pcon->a[index].address);
system("cls");
printf("修改成功!\n");
}
void FindContact(contact* pcon)//查找联系人
{
char name[100];
printf("请输入要查找的联系人:\n");
scanf("%s", name);
int index = FindByName(pcon, name);
if (index == -1)
{
printf("要查找的用户不存在!\n");
return;
}
system("cls");
printf("查找成功!\n");
printf("姓名:%s\n", pcon->a[index].name);
printf("年龄:%d\n", pcon->a[index].age);
printf("性别:%s\n", pcon->a[index].gender);
printf("电话:%s\n", pcon->a[index].telephone);
printf("住址:%s\n", pcon->a[index].address);
}
void ShowContact(contact* pcon)//展示联系人列表
{
if (pcon->size == 0)
{
printf("通讯录为空!\n");
return;
}
printf("姓名 年龄 性别 电话 地址\n");
for (size_t i = 0; i < pcon->size; i++)
{
printf("%s %d %s %s %s\n",
pcon->a[i].name,
pcon->a[i].age,
pcon->a[i].gender,
pcon->a[i].telephone,
pcon->a[i].address);
}
}
void ClearContact(contact* pcon)//清空通讯录
{
pcon->size = 0;
printf("通讯录清空成功!\n");
}
void SaveContact(contact* pcon)//保存通讯录
{
FILE* pf = fopen("contact.txt", "wb");
if (pf == NULL)
{
perror("fopen fail");
return;
}
for (size_t i = 0; i < pcon->size; i++)
{
fwrite(pcon->a + i, sizeof(Info), 1, pf);
}
printf("通讯录数据保存成功!\n");
fclose(pf);
}
void LoadContact(contact* pcon)//载入历史通讯录
{
FILE* pf = fopen("contact.txt", "rb");
if (pf == NULL)
{
perror("fopen fail");
return;
}
Info info;
while (fread(&info, sizeof(Info), 1, pf))
{
SeqListPushBack(pcon, info);
}
printf("通讯录数据载入成功!\n");
fclose(pf);
}
1.2.5 test.c
#include "SeqList.h"
void Menu()
{
printf("****************通讯录******************\n");
printf("****** 1.添加联系人 2.删除联系人 ******\n");
printf("****** 3.修改联系人 4.查找联系人 ******\n");
printf("****** 5.查看通讯录 6.清空通讯录 ******\n");
printf("****** 0.退出通讯录 ******\n");
printf("****************************************\n");
}
int main()
{
contact con;
InitContact(&con); //初始化通讯录
LoadContact(&con); //加载历史通讯录
int option = -1;
do {
Menu();
printf("请选择:\n");
scanf("%d", &option);
system("cls"); //适当的清屏看起来更简洁
switch (option)
{
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;
case 6:
//清空通讯录
ClearContact(&con);
break;
case 0:
//退出通讯录
printf("通讯录退出中...\n");
break;
default:
printf("非法操作,请重新输入\n");
break;
}
} while (option);
SaveContact(&con); //保存通讯录
DestoryContact(&con); //销毁通讯录
return 0;
}
1.3 控制台测试
1.3.1 添加联系人
1.3.2 删除联系人
1.3.3 修改联系人
1.3.4 查找联系人
1.3.5 清空通讯录
1.3.6 通讯录读档和存档
2. 好题测验
2.1 好题展示
【经典算法OJ题1|移除元素】
【经典算法OJ题2|合并两个有序数组】
2.2 答案解析
【移除元素】
int removeElement(int* nums, int numsSize, int val)
{
int left = 0;
for(int right = 0; right < numsSize; right++)
{
if(nums[right] != val)
{
nums[left] = nums[right];
left++;
}
}
return left;
}
【合并两个有序数组】
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n)
{
int p1 = 0, p2 = 0;
int sorted[m + n];
int cur;
while (p1 < m || p2 < n)
{
if (p1 == m)
{
cur = nums2[p2++];
}
else if (p2 == n)
{
cur = nums1[p1++];
}
else if (nums1[p1] < nums2[p2])
{
cur = nums1[p1++];
}
else
{
cur = nums2[p2++];
}
sorted[p1 + p2 - 1] = cur;
}
for (int i = 0; i != m + n; ++i)
{
nums1[i] = sorted[i];
}
}
结语
以上就是小编对顺序表应用的讲解。
如果觉得小编讲的还可以,还请一键三连。互三必回!
持续更新中~!