一.通讯录实现要求
c语言基础要求:结构体、动态内存管理、顺序表、文件操作
二、通讯录功能
能够保存用户信息、能够增加联系人、删除联系人、查找联系人、修改联系人信息、显示联系人信息
三、通讯录实现
通讯录实现90%是基于之前的顺序表的,所以想要实现通讯录可以先去看看我有一篇顺序表的博客(很细很细)
//头文件SeqList.h和contact.h
#pragma once
//SeqList.h
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "contact.h"
typedef struct PersonInfo SLDataType;
typedef struct SeqList
{
SLDataType* arr; //动态内存管理
int size; //有效数据个数
int capacity;//空间大小
}SL;
//顺序表的初始化与销毁
void SLInit(SL* ps);
void SLDestroy(SL* ps);
//顺序表的头部插入与尾部插入
void SLPushFront(SL* ps,SLDataType x);
void SLPushBack(SL* ps,SLDataType x);
//顺序表的头部删除与尾部删除
void SLPopFront(SL* ps);
void SLPopBack(SL* ps);
//在当前位置的前一个位置插入数据
void SLInsert(SL* ps, int pos, SLDataType x);
//删除当前位置数据
void SLErase(SL* ps, int pos);
//查找数据
void SLFind(SL* ps, SLDataType x);
//打印顺序表->进行测试功能
void SLPrint(SL* ps);
#pragma once
//contact.h
#include "SeqList.h"
#define NAME_MAX 50
#define SEX_MAX 15
#define TEL_MAX 50
#define ADDR_MAX 50
typedef struct SeqList contact;
typedef struct PersonInfo
{
char name[NAME_MAX];
char sex[SEX_MAX];
int age;
char tel[TEL_MAX];
char addr[ADDR_MAX];
}PeoInfo;
//初始化/销毁通讯录
void ConInit(contact* con);
void ConDestory(contact* con);
//添加联系人
void ConAdd(contact* con);
//删除联系人
void DelContact(contact* con);
//打印联系人
void ConPrint(contact* con);
//查找联系人
void ConFind(contact* con);
//修改联系人信息
void ModifyContact(contact* con);
//实现文件SeqList.c与contact.c
#define _CRT_SECURE_NO_WARNINGS 1
//SeqList.c
#include "SeqList.h"
//顺序表的初始化
void SLInit(SL* ps)
{
ps->arr = NULL;
ps->capacity = ps->size = 0;
}
//检查空间是否充足
void SLCheckCapacity(SL* ps)
{
if(ps->capacity==ps->size)
{
int newCapacity = ps->capacity == 0 ? 4 : 2 * (ps->capacity);
//初始化时capacity是0 若我们直接写 capacity*=2; 那空间大小就是0*2==0;
//所以用一个三目运算符判断capacity是否为0
//若为0 --- 多给点 给个4 ,若不是0,正常扩大2倍(也可以是1.5倍/1.25倍数等等等等)
//开始扩大空间
SLDataType* tmp = (SLDataType*)realloc(ps->arr, sizeof(ps) * newCapacity);
//记得写sizeof(ps),要不然只扩大4个比特
if (tmp == NULL)//防止扩大失败返回空指针
{
perror("realloc");
exit(1);
}
ps->arr = tmp;
ps->capacity = newCapacity;
}
}
//顺序表的头部插入与尾部插入
void SLPushFront(SL* ps, SLDataType x)
{
assert(ps);
SLCheckCapacity(ps);
for (int i = ps->size; i >0 ; i--)
{
ps->arr[i] = ps->arr[i-1];
//最后:arr[1] = arr[0]
}
ps->arr[0] = x;
ps->size++;
}
void SLPushBack(SL* ps,SLDataType x)
{
assert(ps);
SLCheckCapacity(ps);
//空间经过检查足够,开始尾部插入
ps->arr[ps->size] = x;
ps->size++;
}
//顺序表的头部删除与尾部删除
void SLPopFront(SL* ps)
{
assert(ps);
//既然要删除,就不能传空数组
assert(ps->size);
for (int i = 0; i < ps->size - 1; i++)
{
//arr[size-2] = arr[size-1];
ps->arr[i] = ps->arr[i + 1];
}
ps->size--;
}
void SLPopBack(SL* ps)
{
assert(ps);
assert(ps->size);
ps->size--;
}
//在当前位置的前一个位置插入数据
void SLInsert(SL* ps, int pos, SLDataType x)
{
assert(ps);
SLCheckCapacity(ps);
//注意对pos也有要求,pos必需>=0 &&pos<=size,可以向等,因为空间是足够的,经过检查后,capacity>size
assert(pos >= 0 && pos <= ps->size);
for (int i =ps->size;i>pos;i-- )
{
//arr[pos+1] = arr[pos];
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);//这次不能等于size了,size位置并没有数据
for (int i = pos; i<ps->size-1;i++)
{
ps->arr[i] = ps->arr[i+1];
//arr[pos] = arr[pos+1]
}
ps->size--;
}
//查找数据
//void SLFind(SL* ps, SLDataType x)
//{
// assert(ps);
// int b = -1;
// for (int i = 0; i < ps->size; i++)
// {
// if (ps->arr[i] == x)
// {
// printf("%d ", i);
// b = 1;
// }
// }
// if (b == -1)
// {
// printf("找不到该数据\n");
// }
//}
void SLDestroy(SL* ps)
{
assert(ps);
//但如果arr还没有被分配空间(初始时),就无需释放空间了
if (ps->arr != NULL)
{
free(ps->arr);
}
ps->arr = NULL;
ps->capacity = ps->size = 0;
//ps是函数的临时变量,系统自动销毁,那边传过来的的不是指针的地址,而是&sl,即结构体的地址
}
//顺序表的打印
void SLPrint(SL* ps)
{
for (int i = 0; i < ps->size; i++)
{
printf("%s %s %d %s %s \n", ps->arr[i].name,ps->arr[i].sex,ps->arr[i].age,ps->arr[i].tel,ps->arr[i].addr);
}
//注意,这里用%d只是因为SLDataType暂时是int
printf("\n");
}
#define _CRT_SECURE_NO_WARNINGS 1
//contact.h
#include "contact.h"
#include "SeqList.h"
//初始化/销毁通讯录
void ConInit(contact* con)
{
SLInit(con);
}
//添加联系人
void ConAdd(contact* con)
{
PeoInfo info;
printf("请分别输入要添加的联系人的姓名,性别,年龄,电话号码,住址\n");
scanf("%s %s %d %s %s", info.name, info.sex, &(info.age), info.tel, info.addr);
SLPushBack(con, info);
}
int FindByName(contact* con,char name[NAME_MAX])
{
int i = 0;
for (i = 0; i < con->size; i++)
{
if (0 == strcmp(con->arr[i].name, name));
{
return i;
}
}
return -1;
}
//删除联系人
void DelContact(contact* con)
{
char name[NAME_MAX];
printf("请输入您要删除的联系人的姓名\n");
scanf("%s", name);
int pos = FindByName(con,name);
if (pos==-1)
{
printf("名字输入错误或联系人和不存在\n");
}
else
{
SLErase(con, pos);
printf("已删除\n");
}
}
//打印联系人
void ConPrint(contact* con)
{
if (con->size == 0)
{
printf("还没有联系人\n");
}
SLPrint(con);
}
//查找联系人
void ConFind(contact* con)
{
char name[NAME_MAX];
printf("请输入要查找的联系人姓名\n");
scanf("%s", name);
int pos = FindByName(con, name);
if (pos == -1)
{
printf("要查找的联系人不存在!\n");
}
else
{
printf("%s %s %d %s %s\n",
con->arr[pos].name,
con->arr[pos].sex,
con->arr[pos].age,
con->arr[pos].tel,
con->arr[pos].addr);
}
}
//修改联系人信息
void ModifyContact(contact* con)
{
char name[NAME_MAX];
printf("请输入要修改的联系人姓名\n");
scanf("%s", name);
int pos = FindByName(con, name);
if (pos == -1)
{
printf("要查找的联系人不存在!\n");
}
else
{
printf("请输入要改动的信息\n");
scanf("%s %s %d %s %s", con->arr[pos].name,
con->arr[pos].sex,
&(con->arr[pos].age),
con->arr[pos].tel,
con->arr[pos].addr);
printf("修改完成!");
}
}
void ConDestory(contact* con)
{
SLDestroy(con);
}
//测试文件
#define _CRT_SECURE_NO_WARNINGS 1
//contact test.c
#include"SeqList.h"
#include"contact.h"
void menu()
{
printf("***************************************\n");
printf("*****1.添加联系人 2.删除联系人******\n");
printf("*****3.查找联系人 4.修改联系人******\n");
printf("*****5.全部联系人 0.退出通讯录******\n");
printf("***************************************\n");
}
int main()
{
contact con;
ConInit(&con);
int ch = 0;
do
{
menu();
printf("请输入:\n");
scanf("%d", &ch);
switch (ch)
{
case 1:
ConAdd(&con);
break;
case 2:
DelContact(&con);
break;
case 3:
ConFind(&con);
break;
case 4:
ModifyContact(&con);
break;
case 5:
ConPrint(&con);
break;
case 0:
ConDestory(&con);
break;
default:
printf("请重新输入有效数字:\n");
}
} while(ch);
return 0;
}