基于顺序表实现通讯录项目

片头

在上一篇中,我们学习了什么是顺序表以及如何实现顺序表,今天我们将使用顺序表的结构来完成通讯录的实现,准备好了吗? 我们开始咯!

我们都知道,顺序表实际上就是一个数组,而使用顺序表来实现通讯录,它的本质就是将顺序表中存放的数据类型改为结构体,将联系人的信息存放到结构体中,通过对顺序表的操作来访问通讯录。

因此,我们可以将通讯录理解为套壳的顺序表。 

一、功能

(1)能够保存联系人的姓名、年龄、性别、电话、住址

(2)添加联系人信息

(3)删除联系人信息

(4)修改联系人信息

(5)查找联系人信息

(6)查看通讯录中所有联系人的信息

(7)清空通讯录

二、代码实现

实现通讯录我们要创建5个文件来实现不同的部分:

SeqList.h顺序表定义、头文件引用和顺序表接口函数的声明
SeqList.c顺序表接口函数的实现
Contact.h信息结构体的定义和通讯录函数的声明
Contact.c通讯录函数的实现
test.c界面设计和通讯录主函数实现
(1) SeqList.h

在实现通讯录函数的时候我们可以套用顺序表的接口函数以减轻工作量,但是这并不意味着所有顺序表的函数都能直接照搬。下面展示SeqList.h的代码:

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include"Contact.h"

//顺序表元素种类为存放个人信息的结构体
typedef struct PersonInfo ElemType;

typedef struct SeqList {
	ElemType* arr;
	int size;
	int capacity;
}SL;

//顺序表初始化
void SLInit(SL* ps);
//检查空间,如果为空或者已满,进行扩容
void SLCheckCapacity(SL* ps);
//顺序表尾插
void SLPushBack(SL* ps, ElemType x);
//指定位置删除数据
void SLErase(SL* ps, int pos);
//顺序表销毁
void SLDestroy(SL* ps);
 (2) SeqList.c

SeqList.c 的代码如下:

#include"SeqList.h"

//顺序表初始化
void SLInit(SL* ps) {
	assert(ps);
	ps->arr = NULL;
	ps->capacity = 0;
	ps->size = 0;
}

//顺序表销毁
void SLDestroy(SL* ps) {
	assert(ps);
	if (ps->arr) {
		free(ps->arr);
		ps->arr = NULL;
	}
	ps->capacity = 0;
	ps->size = 0;
}

//扩容
void SLCheckCapacity(SL* ps) {
	assert(ps);
	if (ps->capacity == ps->size) {
		int newCapapcity = ps->capacity == 0 ? 4 : 2 * (ps->capacity);
		ElemType* temp = realloc(ps->arr, sizeof(ElemType) * newCapapcity);
		if (temp == NULL) {
			perror("realloc fail!\n");
			exit(1);
		}
		ps->arr = temp;
		ps->capacity = newCapapcity;
	}
}

//顺序表尾插
void SLPushBack(SL* ps, ElemType x) {
	assert(ps);
	//扩容
	SLCheckCapacity(ps);

	//插入
	ps->arr[ps->size] = x;
	ps->size++;
}

//指定位置删除数据
void SLErase(SL* ps, int pos) {
	assert(ps);
	assert(pos >= 0 && pos < ps->size);
	assert(ps->size != 0);
	for (int i = pos+1; i < ps->size; i++) {
		ps->arr[i-1] = ps->arr[i];
	}
	ps->size--;
}

因为这些在前面的顺序表中已经写过了,这里直接复制粘贴即可。

(3)test.c

在实现通讯录函数之前,我们先把通讯录界面和主函数写出来

创建好test.c后,先包含头文件

#include"SeqList.h"

再设计一下菜单

#include"SeqList.h"
void menu() {
	printf("**************通讯录*******************\n");
	printf("******1.增加联系人  2.删除联系人*******\n");
	printf("******3.查找联系人  4.修改联系人*******\n");
	printf("******5.查看通讯录  6.清空通讯录*******\n");
	printf("******0.退出通讯录              *******\n");
}

主函数如下:

int main() {
	int op = -1;
	Contact con;//通讯录初始化
	SLInit(&con);
	do {
		menu();
		printf("请输入选择: \n");
		scanf("%d", &op);
		switch (op) {
		case 1:
			//添加通讯录数据
			AddContact(&con);
			break;
		case 2:
			//删除通讯录数据
			DelContact(&con);
			break;
		case 3:
			//查找通讯录数据
			FindContact(&con);
			break;
		case 4:
			//修改通讯录数据
			ModifyContact(&con);
			break;
		case 5:
			//展示通讯录数据
			ShowContact(&con);
			break;
		case 6:
			//清空通讯录
			ClearContact(&con);
			break;
		case 0:
			printf("正在退出通讯录....\n");
			break;
		default:
			printf("输入错误,请重新输入!\n");
			break;
		}
	} while (op != 0);

	SLDestroy(&con);//销毁通讯录
	return 0;
}
(4) Contact.h

界面和主函数都写完后,我们开始完成通讯录函数并逐个写入主函数中。

下面时Contact.h的代码:

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>

#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 11
#define ADDR_MAX 100

//前置声明(因为这里不能声明SeqList.h,不然会造成嵌套声明,所以就单独声明一下顺序表)
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];	//住址
}Info;


//初始化通讯录
void InitContact(Contact* pcon);
//添加通讯录数据
void AddContact(Contact* pcon);
//删除通讯录数据
void DelContact(Contact* pcon);
//展示通讯录数据
void ShowContact(Contact* pcon);
//查找通讯录数据
void FindContact(Contact* pcon);
//修改通讯录数据
void ModifyContact(Contact* pcon);
//清空通讯录数据
void ClearContact(Contact* pcon);
//销毁通讯录数据
void DestroyContact(Contact* pcon);
(5) Contact.c

接下来我们展示Contact.c的完整代码

#include"SeqList.h"

//初始化通讯录
void InitContact(Contact* pcon) {
	//pcon->arr = NULL;
	//pcon->capacity = 0;
	//pcon->size = 0;

	SLInit(pcon);
}

//通过姓名来查找联系人
int FindByName(Contact* pcon, char name[]) 
{
	for (int i = 0; i < pcon->size; i++) {
		if (strcmp(pcon->arr[i].name, name) == 0) {
			return i;	//如果找到了,返回下标
		}
	}
	return -1;			//如果没有找到,返回-1
}

//添加通讯录数据
void AddContact(Contact* pcon) {
	assert(pcon);
	Info info;					//创建一个联系人结构体
	printf("请输入姓名: \n");
	scanf("%s", info.name);		
	printf("请输入性别: \n");
	scanf("%s", info.sex);
	printf("请输入年龄: \n");
	scanf("%d", &info.age);
	printf("请输入联系人电话: \n");
	scanf("%s", info.tel);
	printf("请输入联系人的地址: \n");
	scanf("%s", info.addr);

	//保存数据到通讯录(顺序表)
	SLPushBack(pcon, info);
	printf("插入成功!\n");
}

//删除通讯录数据
void DelContact(Contact* pcon) {
	char name[20];
	printf("请输入删除联系人的姓名: \n");
	scanf("%s", name);
	int ret = FindByName(pcon, name);
	if (ret < 0) {
		printf("对不起,没有找到该联系人!\n");
		return;
	}
	
	SLErase(pcon, ret);
	printf("删除联系人成功!\n");
}

//展示通讯录数据
void ShowContact(Contact* pcon) {
	printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");
	for (int i = 0; i < pcon->size; i++) {
		printf("%s %s %d %s %s\n", pcon->arr[i].name,
			pcon->arr[i].sex,
			pcon->arr[i].age,
			pcon->arr[i].tel,
			pcon->arr[i].addr);
	}
}

//查找通讯录数据
void FindContact(Contact* pcon) {
	char name[20];
	printf("请输入要查找联系人的姓名: \n");
	scanf("%s", name);

	int ret = FindByName(pcon, name);
	if (ret < 0) {
		printf("对不起,没找到!\n");
	}
	printf("查找成功!\n");
	printf("姓名: %s\n", pcon->arr[ret].name);
	printf("性别: %s\n", pcon->arr[ret].sex);
	printf("年龄: %d\n", pcon->arr[ret].age);
	printf("电话: %s\n", pcon->arr[ret].tel);
	printf("住址: %s\n", pcon->arr[ret].addr);
}

//修改通讯录数据
void ModifyContact(Contact* pcon) {
	char name[20];
	printf("请输入修改联系人的姓名: \n");
	scanf("%s", name);

	int ret = FindByName(pcon, name);
	if (ret < 0) {
		printf("没有找到联系人!\n");
		return;
	}
	printf("查找成功!\n");
	printf("请输入要修改的联系人姓名: \n");
	scanf("%s", pcon->arr[ret].name);
	printf("请输入要修改的联系人性别: \n");
	scanf("%s", pcon->arr[ret].sex);
	printf("请输入要修改联系人的年龄: \n");
	scanf("%d", &pcon->arr[ret].age);
	printf("请输入要修改联系人的电话: \n");
	scanf("%s", pcon->arr[ret].tel);
	printf("请输入要修改联系人的地址: \n");
	scanf("%s", pcon->arr[ret].addr);

	printf("修改成功!\n");
}

//清空通讯录数据
void ClearContact(Contact* pcon) {
	pcon->size = 0;
	printf("通讯录清空成功!\n");
}

//销毁通讯录数据
void DestroyContact(Contact* pcon) {
	//if (pcon->arr) {
	//	free(pcon->arr);
	//	pcon->arr = NULL;
	//}
	//pcon->capacity = 0;
	//pcon->size = 0;

	SLDestroy(pcon);
	
}

三、测试

(1)添加联系人

选择功能

输入联系人信息

我们查看通讯录检查一下是否真的添加成功

按照相同的步骤再添加一个联系人看看

(2)删除联系人

选择功能

输入要删除的联系人姓名

查看通讯录

联系人“张三” 的确删除了

(3)修改联系人

选择功能

输入修改后的信息

控制台显示修改成功,我们来查看一下

(4)查找联系人

选择功能,输入要查找的联系人姓名

(5) 清空通讯录

我们尝试多添加几个联系人

现在通讯录里有4个人,我们选择清空通讯录

再查看通讯录

通讯录的确被清空了

片尾

今天我们学习了如何用顺序表实现通讯录,希望看完这篇文章能对友友们有所帮助 !  !  !

点赞收藏加关注 !   !   !

谢谢大家 !   !   !

  • 17
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,我们需要定义通讯录的联系人实体类: ```java public class Contact { private String name; private String phoneNumber; private String email; public Contact(String name, String phoneNumber, String email) { this.name = name; this.phoneNumber = phoneNumber; this.email = email; } public String getName() { return name; } public String getPhoneNumber() { return phoneNumber; } public String getEmail() { return email; } @Override public String toString() { return "Name: " + name + ", Phone number: " + phoneNumber + ", Email: " + email; } } ``` 接下来,我们需要实现顺序表类: ```java public class ContactList { private Contact[] contacts; private int size; public ContactList(int capacity) { contacts = new Contact[capacity]; size = 0; } public int getSize() { return size; } public void addContact(Contact contact) { if (size == contacts.length) { throw new RuntimeException("Contact list is full"); } contacts[size++] = contact; } public Contact getContact(int index) { if (index < 0 || index >= size) { throw new RuntimeException("Invalid index"); } return contacts[index]; } public void removeContact(int index) { if (index < 0 || index >= size) { throw new RuntimeException("Invalid index"); } for (int i = index; i < size - 1; i++) { contacts[i] = contacts[i + 1]; } contacts[size - 1] = null; size--; } public void updateContact(int index, Contact contact) { if (index < 0 || index >= size) { throw new RuntimeException("Invalid index"); } contacts[index] = contact; } public Contact[] getAllContacts() { Contact[] result = new Contact[size]; for (int i = 0; i < size; i++) { result[i] = contacts[i]; } return result; } } ``` 然后,我们可以在主函数中使用顺序表类来实现通讯录: ```java public static void main(String[] args) { ContactList contactList = new ContactList(10); contactList.addContact(new Contact("Alice", "1234567890", "alice@example.com")); contactList.addContact(new Contact("Bob", "2345678901", "bob@example.com")); contactList.addContact(new Contact("Charlie", "3456789012", "charlie@example.com")); contactList.removeContact(1); contactList.updateContact(0, new Contact("Alice", "0987654321", "alice@example.com")); Contact[] contacts = contactList.getAllContacts(); for (Contact contact : contacts) { System.out.println(contact); } } ``` 输出结果: ``` Name: Alice, Phone number: 0987654321, Email: alice@example.com Name: Charlie, Phone number: 3456789012, Email: charlie@example.com ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值