目录
通讯录项目要求:
引言:
步骤如下:
用户的数据类型:
初始化循序表:
菜单:
添加联系人:
删除联系人:
修改联系人:
查找联系人:
查看通讯录:
头文件:
(1)Contact.h
(2)Seqlist.h
.c文件
(1)Contact.c
(2)Contest.c
(3)SeqList.c
结语:
c语言基础要求:结构体,动态内存管理,循序表
通讯录功能要求:
(1)至少能够存储100个人的通讯信息
(2)能够保存用户信息:名字,性别,年龄,电话,地址等
(3)增加联系人
(4)查找指定联系人
(5)删除指定联系人
(6)修改指定联系人
(7)显示联系人信息
随着c语言结构体和顺序表的逐渐学习深入,我们就可以完成一个通讯录的小项目,通过实现它来检查自己的学习情况和查缺补漏。
说明:由于通讯录是由循序表的基本运算构成的,故下面的各种操作都只给出在顺序表基础上的完成的,在文章最后会给出循序表的基本运算。
基本运算的函数名如下:
void SLInit(SL* ps) 初始化
void SLDestroy(SL* ps) 销毁
void SLPrint(SL* ps) 打印
void SLCheckCapacity(SL* ps) 扩容
void SLPushBack(SL* ps, ElemType x)尾插
void SLInsert(SL* ps, int pos, ElemType x)指定插入
void SLErase(SL* ps, int pos)删除指定数据
//用户数据
typedef struct PersonInfo
{
char name[NAME_MAX];
char sex[SEX_MAX];
int age;
char number[TEL_MAX];
char address[ADDR_MAX];
}PeoInfo;
基本运算如上面给出的。
void InitContact(contact* con)
{
SLInit(con);
}
void menu()
{
printf("********************通讯录******************\n");
printf("*********1.添加联系人 2.删除联系人*******\n");
printf("*********3.修改联系人 4.查找联系人*******\n");
printf("*********5.查看通讯录 0. 退 出 *******\n");
printf("********************************************\n");
}
效果如下:
peoinfo是自定义的数据结构
void AddContact(contact* con)
{
PeoInfo e;
printf("请输入联系人姓名\n");
scanf("%s", e.name);
printf("请输入联系人年龄\n");
scanf("%d", &e.age);
printf("请输入联系人性别\n");
scanf("%s", e.sex);
printf("请输入联系人电话\n");
scanf("%s", e.number);
printf("请输入联系人住址\n");
scanf("%s", e.address);
SLPushBack(con, e);
}
运行结果如下:
用一个name数组来存储输入的字符串,和通讯录对比若findindex大于0说明该联系人存在删除成功,若小于0说明不存在该联系人删除失败。
查找联系人的函数如下:
int FindNAME(contact* con, char name[])
{
for (int i = 0; i < con->size; i++)
{
if (strcmp(con->arr[i].name, name) == 0)
return i;
}
return -1;
}
void DelContact(contact* con)
{
char name[NAME_MAX];
printf("请输入要查找的联系人姓名\n");
//char name[NAME_MAX];
scanf("%s",name);
int findindex = FindNAME(con, name);
if (findindex >= 0)
{
SLErase(con, findindex);
printf("删除联系人成功\n");
}
else
printf("删除联系人失败\n");
}
运行结果如下:
先查找联系人在进行修改和输入新的联系人,和上面的删除差不多。
void ContactModify(contact*con)
{
char name[NAME_MAX];
printf("请输入要修改联系人名称\n");
scanf("%s", name);
int findindex = FindNAME(con, name);
if (findindex < 0)
{
printf("无此联系人\n");
return;
}
else
{
printf("请输入联系人姓名\n");
scanf("%s", con->arr[findindex].name);
printf("请输入联系人年龄\n");
scanf("%d", &con->arr[findindex].age);
printf("请输入联系人性别\n");
scanf("%s", con->arr[findindex].sex);
printf("请输入联系人电话\n");
scanf("%s", con->arr[findindex].number);
printf("请输入联系人住址\n");
scanf("%s", con->arr[findindex].address);
printf("修改联系人成功\n");
}
}
运行结果如下:
先输入要查找联系人的姓名,后通过FindNAME函数找到联系人对应的下标,进行判断,最后在把联系人对应的信息输出。
void ContactFind(contact* con)
{
printf("请输入要查找的姓名\n");
char name[NAME_MAX];
scanf("%s", name);
int findindex = FindNAME(con, name);
if (findindex < 0)
{
printf("查无此人\n");
return;
}
else
{
printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");
printf("%s %s %d %s %s\n",
con->arr[findindex].name,
con->arr[findindex].sex,
con->arr[findindex].age,
con->arr[findindex].number,
con->arr[findindex].address);
}
}
运行如下:
void ShowContact(contact* con)
{
printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");
for (int i = 0; i < con->size; i++)
{
printf("%s %s %d %s %s\n",
con->arr[i].name,
con->arr[i].sex,
con->arr[i].age,
con->arr[i].number,
con->arr[i].address);
}
}
运行结果如下:
由于是个项目故要进行个功能的函数分装和头文件的引用,故下面我给出头文件和.c文件大家按照我给出的名字在编译器上创建即可运行。
声明通讯录的各种函数及结构体内容。
#pragma once
#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 11
#define ADDR_MAX 100
//前置声明
//用户数据
typedef struct PersonInfo
{
char name[NAME_MAX];
char sex[SEX_MAX];
int age;
char number[TEL_MAX];
char address[ADDR_MAX];
}PeoInfo;
struct SeqList;
typedef struct SeqList contact;
//初始化通讯录
void InitContact(contact* con);
//添加通讯录数据
void AddContact(contact* con);
//删除通讯录数据
void DelContact(contact* con);
//展示通讯录数据
void ShowContact(contact* con);
//查找通讯录数据
void FindContact(contact* con);
//修改通讯录数据
void ModifyContact(contact* con);
//销毁通讯录数据
void DestroyContact(contact* con);
循序表的基本运算
#pragma once
//PeoInfo
#include "Contact.h"
#include
#include
#include
#include
typedef PeoInfo ElemType;
typedef struct SeqList
{
ElemType* arr;
int capacity;
int size;
}SL;
//初始化和销毁
void SLInit(SL* ps);
void SLDestroy(SL* ps);
void SLPrint(SL* ps);
//扩容
void SLCheckCapacity(SL* ps);
//头部插入删除 / 尾部插入删除
void SLPushBack(SL* ps, ElemType x);
void SLPopBack(SL* ps);
void SLPushFront(SL* ps, ElemType x);
void SLPopFront(SL* ps);
//指定位置之前插入/删除数据
void SLInsert(SL* ps, int pos, ElemType x);
void SLErase(SL* ps, int pos);
//int SLFind(SL* ps, ElemType x);
通讯录的函数具体实现。
#define _CRT_SECURE_NO_WARNINGS 1
#include "Contact.h"
#include "Seqlist.h"
void InitContact(contact* con)
{
SLInit(con);
}
void AddContact(contact* con)
{
PeoInfo e;
printf("请输入联系人姓名\n");
scanf("%s", e.name);
printf("请输入联系人年龄\n");
scanf("%d", &e.age);
printf("请输入联系人性别\n");
scanf("%s", e.sex);
printf("请输入联系人电话\n");
scanf("%s", e.number);
printf("请输入联系人住址\n");
scanf("%s", e.address);
SLPushBack(con, e);
}
int FindNAME(contact* con, char name[])
{
for (int i = 0; i < con->size; i++)
{
if (strcmp(con->arr[i].name, name) == 0)
return i;
}
return -1;
}
void DelContact(contact* con)
{
char name[NAME_MAX];
printf("请输入要查找的联系人姓名\n");
//char name[NAME_MAX];
scanf("%s",name);
int findindex = FindNAME(con, name);
if (findindex >= 0)
{
SLErase(con, findindex);
printf("删除联系人成功\n");
}
else
printf("删除联系人失败\n");
}
void ShowContact(contact* con)
{
printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");
for (int i = 0; i < con->size; i++)
{
printf("%s %s %d %s %s\n",
con->arr[i].name,
con->arr[i].sex,
con->arr[i].age,
con->arr[i].number,
con->arr[i].address);
}
}
void ContactModify(contact*con)
{
char name[NAME_MAX];
printf("请输入要修改联系人名称\n");
scanf("%s", name);
int findindex = FindNAME(con, name);
if (findindex < 0)
{
printf("无此联系人\n");
return;
}
else
{
printf("请输入联系人姓名\n");
scanf("%s", con->arr[findindex].name);
printf("请输入联系人年龄\n");
scanf("%d", &con->arr[findindex].age);
printf("请输入联系人性别\n");
scanf("%s", con->arr[findindex].sex);
printf("请输入联系人电话\n");
scanf("%s", con->arr[findindex].number);
printf("请输入联系人住址\n");
scanf("%s", con->arr[findindex].address);
printf("修改联系人成功\n");
}
}
void ContactFind(contact* con)
{
printf("请输入要查找的姓名\n");
char name[NAME_MAX];
scanf("%s", name);
int findindex = FindNAME(con, name);
if (findindex < 0)
{
printf("查无此人\n");
return;
}
else
{
printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");
printf("%s %s %d %s %s\n",
con->arr[findindex].name,
con->arr[findindex].sex,
con->arr[findindex].age,
con->arr[findindex].number,
con->arr[findindex].address);
}
}
void ContactDesTroy(contact* con)
{
SLDestroy(con);
}
主函数,将Contact.c里面的函数调用,用一个swich来进行多功能的通讯录,通过do,while的特性先运行一次再判断要不要继续,符合我们日常玩游戏的逻辑,最后不要忘了一定要销毁我们开辟的空间哦。
#define _CRT_SECURE_NO_WARNINGS 1
#include "Seqlist.h"
void menu()
{
printf("********************通讯录******************\n");
printf("*********1.添加联系人 2.删除联系人*******\n");
printf("*********3.修改联系人 4.查找联系人*******\n");
printf("*********5.查看通讯录 0. 退 出 *******\n");
printf("********************************************\n");
}
int main()
{
contact con;
int op=-1;
InitContact(&con);
do
{
menu();
printf("请选择\n");
scanf("%d", &op);
switch (op)
{
case 1:
//添加联系人
AddContact(&con);
break;
case 2:
DelContact(&con);
break;
//删除联系人
case 3:
ContactModify(&con);
break;
//修改联系人
case 4:
ContactFind(&con);
break;
//查找联系人
case 5:
ShowContact(&con);
break;
//查看通讯录
case 0:
printf("退出程序.....\n");
return 0;
//退 出
default:
printf("输入错误,请重新输入\n");
break;
//
}
} while (op!=0);
ContactDesTroy(&con);
return 0;
}
循序表基本运算的实现。
#define _CRT_SECURE_NO_WARNINGS 1
#include "Seqlist.h"
void SLInit(SL* ps)
{
ps->arr = NULL;
ps->capacity = ps->size = 0;
}
void SLDestroy(SL* ps)
{
free(ps->arr);
ps->capacity = ps->size = 0;
ps = NULL;
}
void SLPrint(SL* ps)
{
for (int i = 0; i < ps->size; i++)
{
printf("%d ", ps->arr[i]);
}
printf("\n");
}
void SLCheckCapacity(SL* ps)
{
if (ps->capacity == ps->size)
{
int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
ElemType* tmp = (ElemType*)realloc(ps->arr, sizeof(ElemType) * newcapacity);
if (tmp == NULL)
{
perror("realloc fail!");
exit(1);
}
ps->arr = tmp;
ps->capacity = newcapacity;
}
}
void SLPushBack(SL* ps, ElemType x)
{
assert(ps);
SLCheckCapacity(ps);
ps->arr[ps->size++] = x;
}
void SLInsert(SL* ps, int pos, ElemType 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--;
}
易错点:
(1)头文件里面不能再包含头文件,及头文件不能嵌套。
(2)对应使用c语言的库函数一定要将对应的头文件带上(如realloc要加上#include
(3)前置声明,因为头文件的引用不能嵌套,故要想引用别的头文件的内容可以进行前置声明例如:
其实写博客不仅仅是为了教大家,同时这也有利于我巩固自己的知识点,和一个学习的总结,由于作者水平有限,对文章有任何问题的还请指出,接受大家的批评,让我改进,如果大家有所收获的话还请不要吝啬你们的点赞收藏和关注,这可以激励我写出更加优秀的文章。