【详解】通讯录项目

发布时间:2024年01月21日

目录

通讯录项目要求:

引言:

步骤如下:

用户的数据类型:

初始化循序表:

菜单:

添加联系人:

删除联系人:

修改联系人:

查找联系人:

查看通讯录:

头文件:

(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文件大家按照我给出的名字在编译器上创建即可运行。

头文件:

(1)Contact.h

声明通讯录的各种函数及结构体内容。

#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);

(2)Seqlist.h

循序表的基本运算

#pragma once
//PeoInfo
#include "Contact.h"
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
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);


.c文件

(1)Contact.c

通讯录的函数具体实现。

#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);
}

(2)Contest.c

主函数,将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;

}

(3)SeqList.c

循序表基本运算的实现。

#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 <stdlib.h>),不带的话运行就会出错,代码一多还很难找到,编译器的提示也不是很准确,故建议大家一用到上面库函数一定要把头文件马上写上不要等到最后再来(会忘掉)。

(3)前置声明,因为头文件的引用不能嵌套,故要想引用别的头文件的内容可以进行前置声明例如:

结语:

其实写博客不仅仅是为了教大家,同时这也有利于我巩固自己的知识点,和一个学习的总结,由于作者水平有限,对文章有任何问题的还请指出,接受大家的批评,让我改进,如果大家有所收获的话还请不要吝啬你们的点赞收藏和关注,这可以激励我写出更加优秀的文章。

文章来源:https://blog.csdn.net/2301_80035594/article/details/135728074
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。