【(数据结构) —— 顺序表的应用-通讯录的实现】

一.通讯录的功能介绍

1.基于动态顺序表实现通讯录

C语言基础要求:结构体、动态内存管理、顺序表、文件件操作

(1). 功能要求

1)至少能够存储100个人的通讯信息
2)能够保存用户信息:名字、性别、年龄、电话、地址等
3)增加联系人信息
4)删除指定联系人
5)查找制定联系人
6)修改指定联系人
7)显示联系人信息

(2).重要思考

思考1】用静态顺序表和动态顺序表分别如何实现
思考2】如何保证程序结束后,历史通讯录信息不会丢失

二. 通讯录的代码实现

1.通讯录的底层结构(顺序表)

(1)思路展示

由于,通讯录是基于动态顺序表实现的,所以掌握基本的顺序表的结构代码,非常重要~!

(2)底层代码实现(顺序表)

1.

SeqList.h
#pragma once
#include"Contact.h"
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>


//typedef int SLDataType;
//更改数据类型为通讯录数据类型
//以下的方式任意选择即可
typedef struct ContactInfo SLDataType;
//typedef CInfo SLDataType;

typedef struct SeqList
{
	SLDataType* a;
	int size;//当前顺序表中的数据有效个数
	int capacity;//顺序表的当前空间的大小
}SL;
//typedef struct SeqList SL;

//对顺序表进行初始化
void SLInit(SL* ps);
void SLDestroy(SL* ps);
//头部/尾部/插入/删除
void SLPushBack(SL* ps, SLDataType x);
void SLPushFront(SL* ps, SLDataType x);
void SLPopBack(SL* ps);
void SLPopFront(SL* ps);

//任意位置/插入/删除
void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps, int pos);

//打印
void SLPrint(SL* ps);
bool SLIsEmpty(SL* ps);

//查找
bool SLFind(SL* ps, SLDataType x);

2.

SeqList.c
#include"SeqList.h"

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

}

void SLCheckCapacity(SL* ps)
{
	//空间不足以插入一个数据,需要扩容
	if (ps->size == ps->capacity)
	{
		//扩容
		int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		SLDataType* tmp = (SLDataType*)realloc(ps->a, newCapacity * sizeof(SLDataType));
		if (tmp == NULL)
		{
			perror("realloc Fail!\n");
			return 1;
		}
		ps->a = tmp;
		ps->capacity = newCapacity;
	}
}

//尾插
void SLPushBack(SL* ps, SLDataType x)
{
	//判断顺序表是否为空
	//assert(ps->a = NULL);
	//暴力方式
	assert(ps);
	//柔和的方式
	/*if (ps->a == NULL)
		return;*/
		//1)空间足够,直接插入
		//2)空间不够,需要扩容
	SLCheckCapacity(ps);
	//空间足够,直接插入
	ps->a[ps->size++] = x;
}
//头插
void SLPushFront(SL* ps, SLDataType x)
{
	assert(ps);

	SLCheckCapacity(ps);
	//空间足够,历史数据后移一位;
	for (size_t i = ps->size; i > 0; i--)
	{
		ps->a[i] = ps->a[i - 1];
	}
	ps->a[0] = x;
	ps->size++;
}
//尾删
void SLPopBack(SL* ps)
{
	assert(ps);
	assert(!SLIsEmpty(ps));
	//ps->a[ps->size - 1] = 0;
	ps->size--;
}

//头删
void SLPopFront(SL* ps)
{
	assert(ps);
	assert(!SLIsEmpty(ps));
	for (size_t i = 1; i < ps->size - 1; i++)
	{
		//最后一次进来的是ps->a[ps->size-2]
		ps->a[i] = ps->a[i + 1];//pa->a[ps->size-2]=ps->a[ps->size-1]
	}
	ps->size--;
}


//任意位置插入
void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	//判断插入的位置是否在范围内
	assert(pos >= 0 && pos <= ps->size);
	SLCheckCapacity(ps);
	//空间足够,把pos的位置及以后的数据往后移一位
	//此处i<ps->size和ps->size-1都可以,但是后面的不步骤需要对应
	for (size_t i = ps->size; i > pos; i--)
	{
		ps->a[i] = ps->a[i - 1];
	}
	/*for (size_t i = ps->size - 1; i > pos; i--)
	{
		ps->a[i+1] = ps->a[i];
	}*/
	ps->a[pos] = x;
	ps->size++;

}
//任意位置删除
void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(!SLIsEmpty(ps));
	assert(pos >= 0 && pos < ps->size);

	//pos位置及以后的数据往前移动一位
	for (size_t i = pos; i < ps->size - 1; i++)
	{
		ps->a[i] = ps->a[i + 1];
	}
	ps->size--;

}

void SLPrint(SL* ps)
{
	for (size_t i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}
bool SLIsEmpty(SL* ps)
{
	assert(ps);
	//这样是不对的,这只是判断空间是否足够
	//return ps->size = ps->capacity;
	return ps->size == 0;
}

//bool SLFind(SL* ps, SLDataType x)
//{
//	scanf("%d", &x);
//	for (size_t i = 0; i < ps->size; i++)
//	{
//		if (ps->a[i] == x)
//		{
//			return true;
//		}
//	}
//	return false;
//}

3.

test.c
#include"SeqList.h"
#include"Contact.h"

//void SLtest()
//{
	//SL sl;
	//SLInit(&sl);

	顺序表的具体操作
	尾插
	//SLPushBack(&sl, 1);
	//SLPushBack(&sl, 2);
	//SLPushBack(&sl, 3);
	//SLPushBack(&sl, 4);
	//SLPrint(&sl);
	头插
	//SLPushFront(&sl, 5);
	//SLPushFront(&sl, 6);
	//SLPushFront(&sl, 7);
	//SLPushFront(&sl, 8);
	//SLPrint(&sl);

	//尾删
	//SLPopBack(&sl);
	//SLPrint(&sl);
	//SLPopBack(&sl);
	//SLPrint(&sl);
	头删
	//SLPopFront(&sl);
	//SLPrint(&sl);
	//SLPopFront(&sl);
	//SLPrint(&sl);

	//任意位置插入删除
	/*SLInsert(&sl, 0, 9);
	SLPrint(&sl);
	SLErase(&sl, 8);
	SLPrint(&sl);

	bool ret = SLFind(&sl, 9);
	if (ret)
		printf("找到了\n");
	else
		printf("没找到\n");
	SLDestroy(&sl);*/
//}
void Contact01()
{
	contact con;
	ContactInit(&con);
	//往通讯录中插入数据
	ContactAdd(&con);
	ContactAdd(&con);
	ContactShow(&con);

	//从通讯录里删除指定的数据
	ContactDel(&con);
	ContactShow(&con);

	//从通讯录里查找指定的联系人
	ContactFind(&con);

	//在通讯录里修改指定的联系人
	ContactModify(&con);
	ContactDestroy(&con);



}
void menu()
{
	printf("***************通讯录****************\n");
	printf("***** 1.添加联系人  2.删除联系人*****\n");
	printf("***** 3.修改联系人  4.查找联系人*****\n");
	printf("***** 5.查看通讯录  0.退出通讯录*****\n");
	printf("*************************************\n");


}
int main()
{
	//SLtest();
	//Contact01();

	int op = -1;
	contact con;
	ContactInit(&con);
	
	do
	{
		menu();
		printf("请选择你要进行的操作:\n");
		scanf("%d", &op);
		switch (op)
		{
		case 1:
			ContactAdd(&con);
			break;
		case 2:
			ContactDel(&con);
			break;
		case 3:
			ContactModify(&con);
			break;
		case 4:
			ContactFind(&con);
			break;
		case 5:
			ContactShow(&con);
			break;
		case 0:
			printf("已退出通讯录\n");
			break;
		default:
			printf("系统里没有找到你需要进行的操作,请重新输入:\n");
			break;

		}
	} while (op != 0);
	ContactDestroy(&con);
	return 0;
}

2.通讯录上层代码实现(通讯录结构)

(1).思路展示

1)由于,通讯录是基于动态顺序表实现的。
2)所以,通讯录上层代码,只需要在上上层代码的头文件代码中创建一个保存联系人的结构,然后再定义通讯录功能函数即可。
3)接着在通讯录上层代码的源文件中将这些功能函数实现即可。
4)基于前面,我们已经知道,通讯录是基于动态顺序表实现的,所以在实现通讯录功能函数时,只需要在通讯录上层代码的源文件中,加上顺序表的头文件就可以调运顺序表的函数来实现通讯录了。

(2).上层代码实现(通讯录)

1.

Contact.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1




//创建保存联系人的结构
#define NAME_MAX 100
#define SEX_MAX 10
#define TEL_MAX 15
#define ADDR_MAX 100

struct ContactInfo
{
	char name[NAME_MAX];//名字
	char sex[SEX_MAX];//性别
	int age;//年龄
	char tel[TEL_MAX];//电话
	char addr[ADDR_MAX];//家庭住址
};
typedef struct ContactInfo CInfo;


//通讯录底层是用顺序表来实现的
typedef struct SeqList contact;


//通讯录的初始化和销毁
void ContactInit(contact* pcon);
void ContactDestroy(contact* pcon);

//添加联系人
void ContactAdd(contact* pcon);
//删除联系人
void ContactDel(contact* pcon);
//修改联系人
void ContactModify(contact* pcon);
//查看通讯录
void ContactShow(contact* pcon);
//查找联系人
void ContactFind(contact* pcon);

2.

Contact.c
#include"Contact.h"
#include"SeqList.h"


//通讯录的初始化与销毁
void ContactInit(contact* pcon)
{
	SLInit(pcon);
}

void ContactDestroy(contact* pcon)
{
	SLDestroy(pcon);
}

//添加联系人
void ContactAdd(contact* pcon)
{
	//接下来获取的都是结构体CInfo结构体里要求的数据
	CInfo 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);

	//联系人数据都获取到了,并保存到了结构体info中
	//往通讯录(顺序表)中插入数据
	SLPushBack(pcon, info);
}

int FindByName(contact* pcon, char name[])
{
	for (int i = 0; i < pcon->size; i++)
	{
		if (strcmp(pcon->a[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}

//删除联系人
void ContactDel(contact* pcon)
{
	//直接强制用户使用名称来查找
	printf("请输入要删除的联系人姓名:\n");
	char name[NAME_MAX];
	scanf("%s", name);
	int findidex = FindByName(pcon, name);
	if (findidex < 0)
	{
		printf("要删除的联系人不存在!\n");
		return;
	}
	//找到了,要删除findidex位置的数据
	SLErase(pcon, findidex);
	printf("删除成功\n");
}

//修改联系人选项
void MondifyMenu()
{
	printf("***************修改联系人选项****************\n");
	printf("***** 1.修改联系人名字  2.修改联系人性别*****\n");
	printf("***** 3.修改联系人年龄  4.修改联系人电话*****\n");
	printf("***** 5.修改联系人住址  0.退出删除选项*******\n");
	printf("******************************************\n");
}
//修改联系人
void ContactModify(contact* pcon)
{
	printf("请输入你需要修改的联系人:\n");
	char name[NAME_MAX];
	scanf("%s", name);
	int find = FindByName(pcon, name);
	if (find < 0)
	{
		printf("要修改的联系人不存在!\n");
		return;
	}
	printf("找到了:\n");
	printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");
	printf("%-5s %-5s %-4d %-4s %-4s\n",
		pcon->a[find].name,
		pcon->a[find].sex,
		pcon->a[find].age,
		pcon->a[find].tel,
		pcon->a[find].addr);
	
	int val = -1;
	do
	{
		MondifyMenu();
		printf("请选择你需要修改的信息:\n");
		scanf("%d", &val);
		switch (val)
		{
		case 1:
			printf("请输入修改后的联系人姓名:\n");
			scanf("%s", pcon->a[find].name);
			break;
		case 2:
			printf("请输入修改后的联系人性别:\n");
			scanf("%s", pcon->a[find].sex);
			break;
		case 3:
			printf("请输入修改后的联系人年龄:\n");
			scanf("%d", &pcon->a[find].age);
			break;
		case 4:
			printf("请输入修改后的联系人电话:\n");
			scanf("%s", pcon->a[find].tel);
			break;
		case 5:
			printf("请输入修改后的联系人住址:\n");
			scanf("%s", pcon->a[find].addr);
			break;
		case 0:
			printf("修改成功\n");
			printf("已退出删除联系人选项\n");
			break;
		default:
			printf("没有找到要修改的选项 请重新选择:\n");
			break;
		}
	} while (val != 0);

	



}
//查看通讯录
void ContactShow(contact* pcon)
{
	//打印表头
	printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");
	for (int i = 0; i < pcon->size; i++)
	{
		printf("%-5s %-5s %-4d %-4s %-4s\n", 
			pcon->a[i].name,
			pcon->a[i].sex,
			pcon->a[i].age,
			pcon->a[i].tel,
			pcon->a[i].addr);
	}


}
//查找指定联系人
void ContactFind(contact* pcon)
{
	printf("请输入你要查找的联系人:\n");
	char name[NAME_MAX];
	scanf("%s", name);
	int findidex = FindByName(pcon, name);
	if (findidex < 0)
	{
		printf("你要查找的联系人不存在!\n");
		return;
	}
	printf("找到了:\n");
	printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");
	printf("%-5s %-5s %-4d %-4s %-4s\n",
			pcon->a[findidex].name,
			pcon->a[findidex].sex,
			pcon->a[findidex].age,
			pcon->a[findidex].tel,
			pcon->a[findidex].addr);
}

3.通讯录代码运行展示(数据只用于测试,无实际意义)

(1)测试展示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(2)升华总结

这里只是展示基于动态顺序表实现通讯录的大致框架,和一些基本功能,有兴趣,能力的小伙伴,也可以下去拓展一下通讯录的其他功能,优化的更加完善,美观的通讯录。
感谢学习!

  • 37
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 28
    评论
第一个模块——主函数main()的功能是:根据选单的选项调用各函数,并完成相应的功能。 
   第二个模块——Menu()的功能是:显示提示选单。 
   第三个模块——Quit()的功能是:退出选单。 
   第四个模块——Create()的功能是:创建新的数据记录。 
   第五个模块——Add()的功能是:增加新的数据记录,并返回选单。 
   第六个模块——Find()的功能是:按要求查询相关的信息,如果找到了,则显示该信息,如果未找到,则提示文件中没有该信息,并返回选单。 
   第七个模块——Alter()[的功能是:修改某条记录的信息,如果未找到要修改的记录,则提示系统中无此记录,并返回选单。 
   第八个模块——Delete()的功能是:删除某条记录,如果未找到要删除的记录,则提示通讯录中没有,并返回选单。 
   第九个模块——List()的功能是:显示所有记录。 一、用链表或者顺序表实现以下系统完成线性表的建立(至少包括10个结点),以及线性表中信息(结点)的插入、查找、删除、修改、输出等操作,具体的模块要求见上方的“总的模块要求”。建议用“文件”存储数据。 1.通讯录管理系统设计实现 (1)通讯者信息包括:编号(char num[10])、姓名(char name[10])、性别(char sex[10])、电话(char phone[20]) (2)除了总的模块要求外,还需统计通讯录中男性人数及女性人数,并求出通讯录中的第一个模块——主函数main()的功能是:根据选单的选项调用各函数,并完成相应的功能。 
   第二个模块——Menu()的功能是:显示提示选单。 
   第三个模块——Quit()的功能是:退出选单。 
   第四个模块——Create()的功能是:创建新的数据记录。 
   第五个模块——Add()的功能是:增加新的数据记录,并返回选单。 
   第六个模块——Find()的功能是:按要求查询相关的信息,如果找到了,则显示该信息,如果未找到,则提示文件中没有该信息,并返回选单。 
   第七个模块——Alter()[的功能是:修改某条记录的信息,如果未找到要修改的记录,则提示系统中无此记录,并返回选单。 
   第八个模块——Delete()的功能是:删除某条记录,如果未找到要删除的记录,则提示通讯录中没有,并返回选单。 
   第九个模块——List()的功能是:显示所有记录。 一、用链表或者顺序表实现以下系统完成线性表的建立(至少包括10个结点),以及线性表中信息(结点)的插入、查找、删除、修改、输出等操作,具体的模块要求见上方的“总的模块要求”。建议用“文件”存储数据。 1.通讯录管理系统设计实现 (1)通讯者信息包括:编号(char num[10])、姓名(char name[10])、性别(char sex[10])、电话(char phone[20]) (2)除了总的模块要求外,还需统计通讯录中男性人数及女性人数,并求出通讯录中的男女比例。 男女比例。
好的,下面是用Java顺序表实现简易通讯录的代码: 首先,在Java中需要定义一个类来表示通讯录中的每一个联系人,这个类包含联系人的姓名和电话号码两个属性: ```java public class Contact { private String name; private String phoneNumber; public Contact(String name, String phoneNumber) { this.name = name; this.phoneNumber = phoneNumber; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPhoneNumber() { return phoneNumber; } public void setPhoneNumber(String phoneNumber) { this.phoneNumber = phoneNumber; } } ``` 接下来,我们用一个顺序表来存储所有的联系人信息: ```java public class ContactList { private Contact[] contacts; private int size; public ContactList(int capacity) { contacts = new Contact[capacity]; size = 0; } public boolean add(Contact contact) { if (size >= contacts.length) { return false; } contacts[size++] = contact; return true; } public boolean remove(int index) { if (index < 0 || index >= size) { return false; } for (int i = index; i < size - 1; i++) { contacts[i] = contacts[i + 1]; } contacts[--size] = null; return true; } public Contact get(int index) { if (index < 0 || index >= size) { return null; } return contacts[index]; } public int size() { return size; } } ``` 在这个类中,我们定义了一个Contact类型的数组来存储所有的联系人信息,同时还有一个size变量来记录当前已经存储的联系人数目。在这个类中,我们提供了以下几个方法: - add(Contact contact):向通讯录中添加一个联系人,如果当前已经存储的联系人数目已经达到了数组的容量,则添加失败。 - remove(int index):根据给定的下标从通讯录中删除一个联系人,如果给定的下标越界,则删除失败。 - get(int index):根据给定的下标获取通讯录中指定位置的联系人,如果给定的下标越界,则返回null。 - size():获取当前通讯录中已经存储的联系人数目。 我们可以使用这个类来实现一个简单的通讯录应用程序,这个程序可以让用户输入联系人的姓名和电话号码,然后将其添加到通讯录中,也可以让用户删除指定位置的联系人,还可以列出所有已经存储的联系人信息。下面是这个应用程序的代码: ```java import java.util.Scanner; public class ContactApp { public static void main(String[] args) { ContactList contactList = new ContactList(10); Scanner scanner = new Scanner(System.in); while (true) { System.out.println("请选择操作:"); System.out.println("1. 添加联系人"); System.out.println("2. 删除联系人"); System.out.println("3. 列出所有联系人"); System.out.println("4. 退出"); int choice = scanner.nextInt(); scanner.nextLine(); switch (choice) { case 1: System.out.println("请输入联系人姓名:"); String name = scanner.nextLine(); System.out.println("请输入联系人电话号码:"); String phoneNumber = scanner.nextLine(); Contact contact = new Contact(name, phoneNumber); if (contactList.add(contact)) { System.out.println("添加成功!"); } else { System.out.println("添加失败,通讯录已满!"); } break; case 2: System.out.println("请输入要删除联系人的下标:"); int index = scanner.nextInt(); if (contactList.remove(index)) { System.out.println("删除成功!"); } else { System.out.println("删除失败,下标越界!"); } break; case 3: System.out.println("所有联系人信息:"); for (int i = 0; i < contactList.size(); i++) { Contact c = contactList.get(i); System.out.println((i + 1) + ". " + c.getName() + " " + c.getPhoneNumber()); } break; case 4: System.out.println("谢谢使用!"); return; default: System.out.println("输入错误,请重新输入!"); break; } } } } ``` 这个应用程序首先创建了一个ContactList对象来存储所有的联系人信息。然后,它通过一个无限循环来等待用户输入选择,并根据用户的选择执行相应的操作。当用户选择退出程序时,程序会结束。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值