顺序表应用——通讯录

news2024/10/6 14:31:37

在本篇之前的顺序表专题我们已经学习的顺序表的实现,了解了如何实现顺序表的插入和删除等功能,那么在本篇当中就要学习基于顺序表来实现通讯录,在通讯录当中能实现联系人的增、删、查改等功能,接下来就让我们一起来实现通讯录吧!
 


 1.实现通讯录前的分析

在实现通讯录的代码前我们要先思考在通讯录项目中能实现什么样的功能
(1)至少能够存储100个人的通讯信息
(2)能够保存用户信息:名字、性别、年龄、电话、地址等
(3)增加联系人信息
(4)删除指定联系人
(5)查找制定联系人
(6)修改指定联系人
(7)显示联系人信息

同时由于在之前的顺序表中使用的是动态顺序表,所以在实现通讯录项目中也基于的是动态顺序表

以下是该通讯录项目的程序文件设置以及各文件中所实现的内容

 

2.通讯录的实现 

2.1 联系人信息的设置以及顺序表内要做出的更改

 由于顺序表的底层就是数组,所以我们就是要利用数组来实现如以下所示的结构

在通讯录中由于我们要存储的是多个联系人的信息,因此要定义一个结构体来存储联系人的信息
以下定义结构体struct PersonIfon来存储联系人的信息,并且使用typedef将该结构体重命名为Persondef
并且在PersonIfon中的每个数组的大小用#define来定义

#define MAX_NAME 20
#define MAX_GENDER 10
#define MAX_TELE 20
#define MAX_ADRESS 50

typedef struct PersonIfon//联系人信息
{
	char name[MAX_NAME];//姓名
	char Gender[MAX_GENDER];//性别
	int age;//年龄
	char Tele[MAX_TELE];//电话
	char Adress[MAX_ADRESS];//地址

}PersonIfon;

同时由于要通讯录所以之前顺序表的Sqelist.h的数组类型也要更改,由用来的整型改变为PersonIfon,要实现该改变就需要在Seqlist.h内代码的头加上#define“contact.h”

这时Seqlist.h就变为以下形式

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

typedef struct PersonIfon SLDataType;
typedef struct Seqlist
{
	SLDataType* arr;
	int size;//有效的数据个数
	int capacity;//空间大小

}SL;//将struct Seqlist重命名为SL

在之前的顺序表的结构体struct Seqlist被重命名为SL,但现在我们要实现的是通讯录这时这个名字就不太合适与直观,那该如何来在contact.h文件内对struct Seqlist进行重命名呢?
这时你可能想到是在contact.h内加上预处理指令#define“Seqlist.h”,
但这样就存在问题了,在之前的操作中我们已经在Seqlaist.h文件内包含了contact.h,如果在这再在contact.h内包含Seqlist.h就会存在头文件相互包含的问题,这时程序就会崩溃

所以正确的解决方法是什么呢?
其实这时只需要在contact.h中先声明以下struct Seqlist就可以对该结构体进行重命名了

struct Seqlist;
typedef struct Seqlist contact;

2.2  通讯录的初始化以及销毁


在以上完成联系人结构体的定义以及对顺序表内数组类型的更改,接下来就可以来实现通讯录初始化和销毁的函数了

在此先在contact.h内声明初始化函数以及销毁函数,由于在此要对通讯录内容进行更改,所以要进行传址调用,两个函数的参数都是结构体指针

void ContactInit(contact* con);//初始化通讯录
void ContactDestory(contact* con);//销毁通讯录

声明完之后就是在contact.c内实现以上两个函数,在此通讯录的初始化以及销毁内就可以直接调用之前顺序表的初始化以及销毁函数了

void ContactInit(contact* con)//通讯录初始化
{
	SLInit(con);
}
void ContactDestory(contact* con)//销毁通讯录
{
	SLDestory(con);
}

2.3通讯录的展示 

通讯录的展示就是将通讯录的信息都打印出来,实质就是要遍历一般数组
在此在printf中在占位符中的%后加入的最小宽度限制来让打印出的通讯录更有顺序

void ContactShow(contact* con)//展示通讯录
{
	printf("%-10s %-4s %-4s %15s %-20s\n", "姓名", "性别", "年龄", "电话", "地址");
	for (int i = 0; i < con->size; i++)
	{
		printf("%-10s %-4s %-4d %15s %-20s\n",
			con->arr[i].name,
			con->arr[i].Gender,
			con->arr[i].age,
			con->arr[i].Tele,
			con->arr[i].Adress);
	}
}

2.4通讯录各功能实现

在以上完成了通讯录的初始化和销毁接下来我们就来实现通讯录增、删、查、改的功能了

2.4.1 通讯录内添加联系人 

在此要实现通讯录中联系人的增加先在contact.h内对增加联系人函数进行声明,由于在此要对通讯录内容进行更改,所以要进行传址调用,函数的参数是结构体指针

void ContactAdd(contact* con);//通讯录内添加联系人

接下来就是在contact.c内完成添加联系人的函数
在此先创建一个结构体PersonIfon ifon,并且使用scanf来读取用户输入的此联系人的各信息存储在结构体ifon内,再调用顺序表中的插入函数将该结构体ifon插入到数组内,在此使用的是尾插函数,也可以使用其他插入方法

void ContactAdd(contact* con)//在通讯录内添加联系人
{
	PersonIfon ifon;
	printf("请输入联系人姓名:\n");
	scanf("%s", &ifon.name);
	printf("请输入联系人性别:\n");
	scanf("%s", &ifon.Gender);
	printf("请输入联系人年龄:\n");
	scanf("%d", &ifon.age);
	printf("请输入联系人电话:\n");
	scanf("%s", &ifon.Tele);
	printf("请输入联系人地址:\n");
	scanf("%s", &ifon.Adress);

	SLPushBack(con, ifon);
}

2.4.2 通讯录内删除联系人

在此要实现通讯录中联系人的删除先在contact.h内对删除联系人函数进行声明,由于在此要对通讯录内容进行更改,所以要进行传址调用,函数的参数是结构体指针

void ContactDel(contact* con);//通讯录内删除联系人

在声明完函数之后就是对该函数的实现,但在删除通讯录内的联系人要通讯录中存在要删除的联系人才能删除,所以在函数内还要先判断,但之后通讯录的其他功能可能还要用到查找联系人是否存在

所以可以直接在创建一个判断相关联系人是否存在的函数,在此根据的是名字来查找联系人

存在该联系人就返回相应的数组下标,不存在就返回-1

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

接下来就是在contact.c内完成删除联系人的函数
在此函数内先定义一个char类型的数组name,大小为MAX_NAME。用scanf将用户输入的联系人姓名存放在该数组内,之后再将指针con与name作为FindbyName的参数,通过FindbyName函数的返回值来得到要删除的联系人是否存在。若返回值小于0则说明该联系人不存在,之后就直接退出函数ContactDel,否则就调用顺序表中的任意位置的删除函数SLErase,这时tmp就是要删除的数组下标

void ContactDel(contact* con)//通讯录内删除联系人
{
	char name[MAX_NAME];
	printf("请输入要删除的联系人的姓名\n");
	scanf("%s", name);
	int tmp = FindbyName(con, name);
	if (tmp < 0)
	{
		printf("该联系人不存在,删除失败\n");
		return;
	}
	SLErase(con, tmp);
	printf("删除成功\n");

}

 2.4.3 通讯录内修改联系人

在此要实现通讯录中联系人的修改先在contact.h内对修改联系人函数进行声明,由于在此要对通讯录内容进行更改,所以要进行传址调用,函数的参数是结构体指针

void ContactModify(contact* con);//通讯录内修改联系人

 接下来就是在contact.c内完成修改联系人的函数
在该函数内和删除联系人函数一样也是先在此函数内先定义一个char类型的数组name,大小为MAX_NAME。用scanf将用户输入的联系人姓名存放在该数组内,之后再将指针con与name作为FindbyName的参数,通过FindbyName函数的返回值来得到要修改的联系人是否存在。若返回值小于0则说明该联系人不存在,之后就直接退出函数ContactDel。否则就使用scanf将用户输入的信息存放到原来联系人的数组位置

void ContactModify(contact* con)//修改联系人信息
{
	char name[MAX_NAME];
	printf("请输入要修改的联系人的姓名\n");
	scanf("%s", name);
	int tmp = FindbyName(con, name);
	if (tmp < 0)
	{
		printf("该联系人不存在,修改失败\n");
		return;
	}
	//直接修改
	printf("请输入新的联系人姓名:\n");
	scanf("%s", con->arr[tmp].name);
	printf("请输入新的联系人性别:\n");
	scanf("%s", con->arr[tmp].Gender);
	printf("请输入新的联系人年龄:\n");
	scanf("%d", &con->arr[tmp].age);
	printf("请输入新的联系人电话:\n");
	scanf("%s", con->arr[tmp].Tele);
	printf("请输入新的联系人地址:\n");
	scanf("%s", con->arr[tmp].Adress);

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

}

 2.4.4 通讯录内查找联系人

 在此要实现通讯录中联系人的修改先在contact.h内对修改联系人函数进行声明,在此虽然查找联系人未对通讯录内数据进行修改,但在此还是将结构体作为函数的参数,原因通讯录其他函数都是传地址在此也保持一致性

void ContactFind(contact* con);//在通讯录内查找联系人

  接下来就是在contact.c内完成查找联系人的函数

在该函数内也是先定义一个char类型的数组name,再通过scanf函数将用户输入的字符串存储到数组内,在此并定义一个变量flag=-1再通过for循环遍历数组中的各个元素中的name是否和数组name相同相同就将flag赋值为1,相同就打印该元素的联系人信息,当遍历完时flag如果等于-1就打印查找不到联系人

void ContactFind(contact* con)//查找联系人
{
	char name[MAX_NAME];
	printf("请输入要查找的联系人的姓名\n");
	scanf("%s", name);
	int flag = -1;
	for (int i = 0; i < con->size; i++)
	{
		if (strcmp(con->arr[i].name, name) == 0)
		{
			flag = 1;
			printf("查找成功!\n");
			printf("%-10s %-4s %-4s %15s %-20s\n", "姓名", "性别", "年龄", "电话", "地址");
			
			printf("%-10s %-4s %-4d %15s %-20s\n",
				con->arr[i].name,
				con->arr[i].Gender,
				con->arr[i].age,
				con->arr[i].Tele,
				con->arr[i].Adress);
			
		}

	}
	if (flag == -1)
	{
		printf("你所要查找的联系人不存在!\n");
	}

}

 

3.通讯录test.c文件

在以上我们已经实现了通讯录各种功能,现在就需要在test.c内将这些设计好的功能给拼装起来,让程序能在运行窗口通过输入不同的数就可以实现通讯录的各功能
 

注:在test.c的开头要加上#include"SeqList.h"和#include"contact.h"

先在test.c内先创建main函数,同时要实现对通讯录的多次操作就需要用到循环,在此用的是do...while循环,在循环内在创建一个switch语句来实现用户输入不同的信息就进入不同的函功能。在switch语句内的case后的常量都使用枚举所定义的,这样会使得代码的可读性更高、同时shitch语句的case语句排序也可以是不按顺序来的。在不同的case语句内就调用不同的通讯录功能函数
 

在进入循环先初始化顺序表,退出循环就销毁顺序表 

#include"SeqList.h"
#include"contact.h"


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

}

enum option
{
	 ADD=1,
     DEL=2,
	 FIND=3,
     MODIFY=4,
     SHOW=5

};


int main()
{
	int input = 0;
	contact con;
	ContactInit(&con);
	do
	{
		menu();
		printf("请选择操作\n");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			 ContactAdd(&con);
			break;
		case DEL:
			ContactDel(&con);
			break;
		case FIND:
			ContactFind(&con);
			break;
		case MODIFY:
			ContactModify(&con);
			break;
		case SHOW:
			ContactShow(&con);
			break;
		default:
			printf("选择操作错误,请输入1~5内的数\n");
			break;

		}


	} while(input);//当输入的值为0时,input值也就也0,在此判断部分input就为假就会退出循环
	ContactDestory(&con);


	return 0;
}

 

4. 通讯录读取历史数据和保存数据

在之前已经实现了通讯录的各功能的数据只能在程序运行窗口打开的时候进行通讯录的增、删、查、改等功能。在关闭窗口后对通讯录进行的各项操作都不会保存,那么要怎么样才能让我们设计的通讯录在每次开始之前都读取之前的信息,在结束后都保存通讯录的信息呢?

在之前文件操作章节中讲解了如何将程序数据输出到文件中,将文件数据输入到程序当中,所以在通讯录中我们就可以用到文件操作的相关函数来实现通讯录数据的保存与读取。

 

4.1读取历史数据

要读取历史数据就要在通讯录每次初始化之后就输入文件的信息到所创建的通讯录中,也就是将输入到数组当中。

在此先在我们创建的程序的文件夹中创建一个con.txt文本,再使用fopen以读的方式打开文件,再创建一个PersonIfon ifon的变量,之后在使用到fread以二进制的形式输入文件的信息到创建的ifon中,再将ifon尾插到数组当中。

void ContactRead(contact* con)//从文件中读取历史数据
{
	FILE* pf = fopen("con.txt", "rb");
	if (pf == NULL)
	{
		perror("fopen");
		return;
	}
	PersonIfon ifon;
	while (fread(&ifon, sizeof(PersonIfon), 1, pf))
	{
		SLPushBack(con, ifon);
	}
	printf("成功读取历史数据到通讯录中\n");
}

 

在通讯录初始化函数中调用SLInit函数后调用COntactRead就可以实现历史数据的读取

void ContactInit(contact* con)//通讯录初始化
{
	SLInit(con);
	ContactRead(con);
}

 

4.2 保存数据

要实现通讯录每次在退出程序后都能将数据保留,这就需要在每次销毁通讯录前将通讯录内的数据,也就是数组的所有元素都输出到con.txt文件内。

要把数组的所有元素都输出到con.txt文件内就需要先以写的方式打开文件,后在循环的使用fwrite将数组的数据以二进制的形式输出到文件当中

void ContactWrite(contact* con)//将通讯录数据读入文件中
{
	FILE* pf = fopen("con.txt", "wb");
	if (pf == NULL)
	{
		perror("fopen\n");
		return;
	}
	
	for (int i = 0; i < con->size; i++)
	{
		fwrite(con->arr+i, sizeof(PersonIfon), 1, pf);

	}
	printf("通讯录数据保存成功\n");
}

 

在通讯录销毁函数中调用SLDestory函数前调用COntactWrite就可以实现数据输出到文件当中,也就将数据保留了下来

void ContactDestory(contact* con)//销毁通讯录
{
	ContactWrite(con);
	SLDestory(con);
}

 


通讯录完整代码 
 

注:在Seqlist.h和Seqlist.c内的查找和打印顺序表与以上代码不兼容,运行时会使得程序崩溃,所以将这些部分注释掉 

contact.h 

#pragma once
#define MAX_NAME 20
#define MAX_GENDER 10
#define MAX_TELE 20
#define MAX_ADRESS 50


typedef struct PersonIfon//联系人信息
{
	char name[MAX_NAME];//姓名
	char Gender[MAX_GENDER];//性别
	int age;//年龄
	char Tele[MAX_TELE];//电话
	char Adress[MAX_ADRESS];//地址

}PersonIfon;

struct Seqlist;
typedef struct Seqlist contact;
 
void ContactInit(contact* con);//初始化通讯录
void ContactDestory(contact* con);//销毁通讯录
void ContactAdd(contact* con);//通讯录内添加联系人
void ContactDel(contact* con);//通讯录内删除联系人
void ContactModify(contact* con);//通讯录内修改联系人
void ContactFind(contact* con);//在通讯录内查找联系人
void ContactShow(contact* con);//展示通讯录

void ContactRead(contact* con);//从文件中读取历史数据
void ContactWrite(contact* con);//将通讯录数据读入文件中

 

Seqlist.h

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>

typedef struct PersonIfon SLDataType;
typedef struct Seqlist
{
	SLDataType* arr;
	int size;//有效的数据个数
	int capacity;//空间大小

}SL;//将struct Seqlist重命名为SL

void SLInit(SL* ps);//初始化
void SLDestory(SL* ps);//销毁

void SLCheckCapacity(SL* ps);//检查空间是否足够
//void SLPrint(SL ps);//打印顺序表


void SLPushBack(SL* ps, SLDataType x);//尾插
void SLPushPront(SL* ps, SLDataType x);//头插


void SLPopBack(SL* ps);//尾删
void SLPopPront(SL* ps);//头删

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

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

 

 

Seqlist.c 

#include"SeqList.h"


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

void SLDestory(SL* ps)//顺序表销毁
{
	if (ps->arr)
	{
		free(ps->arr);

	}
	ps->arr = 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->arr, newcapacity * sizeof(SLDataType));
		if (tmp == NULL)
		{
			perror("realloc");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newcapacity;

	}
}

//void SLPrint(SL ps)//打印
//{
//	int i = 0;
//	for (i; i < ps.size; i++)
//	{
//		printf("%d ", ps.arr[i]);
//	}
//	printf("\n");
//}


void SLPushBack(SL* ps, SLDataType x)//尾插
{
	assert(ps);
	SLCheckCapacity(ps);

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

void SLPushPront(SL* ps, SLDataType x)//头插
{
	assert(ps);
	SLCheckCapacity(ps);
	for (int i = ps->size; i > 0; i--)
	{
		ps->arr[i] = ps->arr[i - 1];   //pa->arr[1]=pa->arr[0]
	}
	ps->arr[0] = x;
	ps->size++;
}


void SLPopBack(SL* ps)//尾删
{
	assert(ps);
	assert(ps->size);
	ps->size--;
}

void SLPopPront(SL* ps)//头删
{
	assert(ps);
	assert(ps->size);
	for (int i = 0; i < ps->size - 1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];

	}
	ps->size--;
}


void SLInsert(SL* ps, int pos, SLDataType 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+1] = ps->arr[pos]
	}
	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 - 2; i++)
	{
		ps->arr[i] = ps->arr[i + 1];//结束条件ps->arr[ps->size-2] = ps->arr[ps->size-1]
	}
	--ps->size;
}


//int SLFind(SL* ps, SLDataType x)//查找
//{
//	assert(ps);
//	for (int i = 0; i < ps->size; i++)
//	{
//		if (ps->arr[i] == x)
//		{
//			return i;
//		}
//	}
//	return -1;
//
//}

 

contact.c 

#pragma once
#include "contact.h"
#include"SeqList.h"



void ContactRead(contact* con)//从文件中读取历史数据
{
	FILE* pf = fopen("con.txt", "rb");
	if (pf == NULL)
	{
		perror("fopen");
		return;
	}
	PersonIfon ifon;
	while (fread(&ifon, sizeof(PersonIfon), 1, pf))
	{
		SLPushBack(con, ifon);
	}
	printf("成功读取历史数据到通讯录中\n");
}

void ContactInit(contact* con)//通讯录初始化
{
	SLInit(con);
	ContactRead(con);

}

void ContactWrite(contact* con)//将通讯录数据读入文件中
{
	FILE* pf = fopen("con.txt", "wb");
	if (pf == NULL)
	{
		perror("fopen\n");
		return;
	}
	
	for (int i = 0; i < con->size; i++)
	{
		fwrite(con->arr+i, sizeof(PersonIfon), 1, pf);

	}
	printf("通讯录数据保存成功\n");
}







void ContactDestory(contact* con)//销毁通讯录
{
	ContactWrite(con);
	SLDestory(con);

}

void ContactAdd(contact* con)//在通讯录内添加联系人
{
	PersonIfon ifon;
	printf("请输入联系人姓名:\n");
	scanf("%s", &ifon.name);
	printf("请输入联系人性别:\n");
	scanf("%s", &ifon.Gender);
	printf("请输入联系人年龄:\n");
	scanf("%d", &ifon.age);
	printf("请输入联系人电话:\n");
	scanf("%s", &ifon.Tele);
	printf("请输入联系人地址:\n");
	scanf("%s", &ifon.Adress);

	SLPushBack(con, ifon);

}

int FindbyName(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 ContactDel(contact* con)//通讯录内删除联系人
{
	char name[MAX_NAME];
	printf("请输入要删除的联系人的姓名\n");
	scanf("%s", name);
	int tmp = FindbyName(con, name);
	if (tmp < 0)
	{
		printf("该联系人不存在,删除失败\n");
		return;
	}
	SLErase(con, tmp);
	printf("删除成功\n");


}

void ContactModify(contact* con)//修改联系人信息
{
	char name[MAX_NAME];
	printf("请输入要修改的联系人的姓名\n");
	scanf("%s", name);
	int tmp = FindbyName(con, name);
	if (tmp < 0)
	{
		printf("该联系人不存在,修改失败\n");
		return;
	}
	
	printf("请输入新的联系人姓名:\n");
	scanf("%s", con->arr[tmp].name);
	printf("请输入新的联系人性别:\n");
	scanf("%s", con->arr[tmp].Gender);
	printf("请输入新的联系人年龄:\n");
	scanf("%d", &con->arr[tmp].age);
	printf("请输入新的联系人电话:\n");
	scanf("%s", con->arr[tmp].Tele);
	printf("请输入新的联系人地址:\n");
	scanf("%s", con->arr[tmp].Adress);


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

}



void ContactFind(contact* con)//查找联系人
{
	char name[MAX_NAME];
	printf("请输入要查找的联系人的姓名\n");
	scanf("%s", name);
	int flag = -1;
	for (int i = 0; i < con->size; i++)
	{
		if (strcmp(con->arr[i].name, name) == 0)
		{
			flag = 1;
			printf("查找成功!\n");
			printf("%-10s %-4s %-4s %15s %-20s\n", "姓名", "性别", "年龄", "电话", "地址");
			
			printf("%-10s %-4s %-4d %15s %-20s\n",
				con->arr[i].name,
				con->arr[i].Gender,
				con->arr[i].age,
				con->arr[i].Tele,
				con->arr[i].Adress);
			
		}

	}
	if (flag == -1)
	{
		printf("你所要查找的联系人不存在!\n");
	}


}

void ContactShow(contact* con)//展示通讯录
{

	printf("%-10s %-4s %-4s %15s %-20s\n", "姓名", "性别", "年龄", "电话", "地址");
	for (int i = 0; i < con->size; i++)
	{
		printf("%-10s %-4s %-4d %15s %-20s\n",
			con->arr[i].name,
			con->arr[i].Gender,
			con->arr[i].age,
			con->arr[i].Tele,
			con->arr[i].Adress);
	}
}

 

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

}

enum option
{
	 ADD=1,
     DEL=2,
	 FIND=3,
     MODIFY=4,
     SHOW=5

};



int main()
{
	int input = 0;
	contact con;
	ContactInit(&con);
	do
	{
		menu();
		printf("请选择操作\n");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			 ContactAdd(&con);
			break;
		case DEL:
			ContactDel(&con);
			break;
		case FIND:
			ContactFind(&con);
			break;
		case MODIFY:
			ContactModify(&con);
			break;
		case SHOW:
			ContactShow(&con);
			break;
		default:
			printf("选择操作错误,请输入1~5内的数\n");
			break;

		}




	} while(input);
	ContactDestory(&con);


	return 0;
}

通讯录实现效果 
 

基于顺序表实现通讯录

 

以上就是本篇的所有内容了,希望能得到你的点赞与收藏,感谢支持!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1879790.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

民用无人机企业招标投标需要资质证书详解

一、基础资质 在民用无人机企业的招标投标过程中&#xff0c;基础资质是首要考虑的因素。这些资质通常包括企业注册资质、税务登记证、组织机构代码证等。 1.1 企业注册资质 企业应具备合法的注册资质&#xff0c;即营业执照。该执照应包含企业名称、注册地址、法定代表人、…

Java [数据结构] Deque与Queue

&#x1f93a;深入理解 Java 中的 Deque 和 Queue&#x1f93a; 在现代软件开发中&#xff0c;数据结构是构建高效、可维护代码的基础。 Java 作为一门广泛应用的编程语言&#xff0c;其丰富的集合框架&#xff08;Collections Framework&#xff09;为开发者提供了多种强大的…

Zabbix 排坑版 Centos7

systemctl stop firewalld;systemctl disable firewalld;setenforce 0sed -i s/SELINUXenforcing/SELINUXdisabled/ /etc/selinux/configzabbix源地址,可以自己选版本&#xff0c;安装都大差不差 rpm -Uvh https://repo.zabbix.com/zabbix/5.0/rhel/7/x86_64/zabbix-release-5…

【车载开发系列】S32 Design Studio工具安装步骤

【车载开发系列】S32 Design Studio工具安装步骤 S32 Design Studio工具安装步骤 【车载开发系列】S32 Design Studio工具安装步骤※关键字提炼※一. 准备工作二. 下载安装包三. 获取License许可四. 开始预安装五. 开始正式安装六. 启动软件七. 安装插件八. 卸载插件九. 确认安…

【操作系统】进程管理——进程控制和进程通信(个人笔记)

学习日期&#xff1a;2024.6.30 内容摘要&#xff1a;进程控制的概念&#xff0c;进程控制相关的“原语”&#xff0c;进程通信 进程控制 原语 进程控制用“原语”实现。原语是一种特殊的程序&#xff0c;它的执行具有原子性&#xff0c;也就是说&#xff0c;这段程序的执行…

vs code python开发笔记

目录 选择python 解析器 安装插件 不全&#xff1a; 调试启动目录问题&#xff1a; 2.选择python解释器 选择python 解析器 ctrl shift P select interpreter 安装插件 不全&#xff1a; remote ssh python debuger 左下角&#xff0c;点击左右左右箭头&#xff0c;远程…

后端之路第三站(Mybatis)——JDBC跟Mybatis、lombok

一、什么是JDBC JDBC就是sun公司研发的一套通过java来操控数据库的工具&#xff0c;对应不同的数据库系统有不同的JDBC&#xff0c;而他们统称【驱动】&#xff0c;这就是上一篇我们提到创建Mybatis项目时要引入的依赖、以及连接数据库四要素里的第一要素。 JDBC有自己一套原始…

Redis 7.x 系列【8】数据类型之哈希(Hash)

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Redis 版本 7.2.5 源码地址&#xff1a;https://gitee.com/pearl-organization/study-redis-demo 文章目录 1. 概述2. 常用命令2.1 HSET2.2 HGET2.3 HDEL2.4 HEXISTS2.5 HGETALL2.6 HKEYS2.7 HLE…

grpc学习golang版( 五、多proto文件示例 )

系列文章目录 第一章 grpc基本概念与安装 第二章 grpc入门示例 第三章 proto文件数据类型 第四章 多服务示例 第五章 多proto文件示例 第六章 服务器流式传输 第七章 客户端流式传输 第八章 双向流示例 文章目录 一、前言二、定义proto文件2.1 公共proto文件2.2 语音唤醒proto文…

探索MySQL核心技术:理解索引和主键的关系

在数据密集型应用中&#xff0c;数据库的性能往往是决定一个应用成败的重要因素之一。其中&#xff0c;MySQL作为一种开源关系型数据库管理系统&#xff0c;以其卓越的性能和丰富的功能被广泛应用。而在MySQL数据库优化的众多技巧中&#xff0c;索引和主键扮演着极其重要的角色…

5、Python之rich:GUI之外,终端呈现也能玩出花

引言 在Python系列文章的上一篇中&#xff0c;我们从print的定义出发&#xff0c;进一步探索了print()函数更多的用法&#xff0c;尤其是一些哪怕是Python老手也可能忽略的用法。没有阅读的或者需要回顾print()及输出格式化的扩展用法&#xff0c;可以查看上一篇文章。 虽然pr…

2024/6/30周报

文章目录 摘要ABSTRACT文献阅读题目问题本文贡献方法LSTMTCN模型总体架构 实验实验结果 深度学习TCN-LSTM代码运行结果 总结 摘要 本周阅读了一篇关于TCN和LSTM进行光伏功率预测的文章&#xff0c;本文提出了一种利用LSTM-TCN预测光伏功率的新模型。它由长短期记忆和时间卷积网…

可编程定时计数器8253/8254 - 8253控制字

8253控制字 概述 图7-45中左下角的是控制字寄存器&#xff0c;其操作端口是0x43,它是8位大小的寄存器 控制字寄存器也称为模式控制器&#xff0c;在控制字寄存器中保存的内容称为控制字&#xff0c;控制字用来设置所指定的计数器(通道)的工作方式、读写格式及数制&#xff0c…

emptyDir + initContainer实现ConfigMap的动态更新(K8s相关)

1. 絮絮叨叨 K8s部署服务时&#xff0c;一般都需要使用ConfigMap定义一些配置文件例如&#xff0c;部署分布式SQL引擎Presto&#xff0c;会在ConfigMap中定义coordinator、worker所需的配置文件以node.properties为例&#xff0c;node.environment和node.data-dir的值将由Helm…

48 - 按日期分组销售产品(高频 SQL 50 题基础版)

48 - 按日期分组销售产品 -- group_concat 分组拼接selectsell_date,count(distinct product) num_sold,group_concat(distinct product order by product separator ,) products fromActivities group bysell_date;

监控电脑的软件有哪些?精选8大监控电脑的软件

根据当前市场反馈和功能评价&#xff0c;以下是八款备受推崇的电脑监控软件推荐&#xff0c;适合不同企业和组织的监控与管理需求&#xff1a; 1.安企神监控软件 特点&#xff1a;全面的局域网监控工具&#xff0c;擅长网络设备监控、网络性能管理和故障诊断。提供员工电脑屏幕…

C++操作系列(二):VSCode安装和配置C++开发环境

1. VSCode下载 进入VSCode的官网网页&#xff1a;Download Visual Studio Code - Mac, Linux, Windows 下载相应的版本&#xff1a; 2. 安装VSCode 安装到指定位置&#xff1a; 一路下一步&#xff0c;直至安装完成&#xff1a; 3. 安装C插件 3.1. 安装C/C 点击扩展图标&…

语音唤醒入门(基于ESP-skainet)

主要参考资料&#xff1a; ESP-SR 用户指南: https://docs.espressif.com/projects/esp-sr/zh_CN/latest/esp32s3/index.html 目录 ESP提供的模型直接初始化和使用模型AFE声学前端算法 使用模型 自定义模型 ESP提供的模型 乐鑫提供了经过训练的 WakeNet 和 MultiNet 模型&…

《高考择校择专业:权衡与抉择的智慧》

分数限制下&#xff0c;选好专业还是选好学校&#xff1f; 2024 年高考的大幕已然落下&#xff0c;然而对于众多考生而言&#xff0c;新的挑战才刚刚开始。在分数既定的情况下&#xff0c;是优先选择心仪的专业&#xff0c;还是更看重知名度高的学校&#xff1f;这无疑是一个令…

Go线程实现模型-核心元素的容器

核心元素的容器 图例 作用 3个全局容器存在的主要目的&#xff0c;都是为了罗列某个核心元素的全部 与G相关的调度器 与G相关的那4个非全局容器&#xff1a;调度器的可运行G队列、调度器的自由G队列、本地P的可运行G队列&#xff0c;以及本地P的自由G列表 全局G列表 任何…