数据结构 - 顺序表实现通讯录

test.c文件

#define _CRT_SECURE_NO_WARNINGS 1#include "Contact.h"
int main() 
{Con myContacts;ConInit(&myContacts);int choice;int index;char targetName[100];PerInfo contact; // 创建一个新的联系人信息实例while (1) {printf("\n--- 通讯录管理系统 ---\n");printf("1. 添加联系人到末尾\n");printf("2. 添加联系人到开头\n");printf("3. 删除最后一个联系人\n");printf("4. 删除第一个联系人\n");printf("5. 显示所有联系人信息\n");printf("6. 保存通讯录到文件\n");printf("7. 从文件加载通讯录\n");printf("8. 修改指定联系人的信息\n");printf("9. 查找指定联系人的信息\n");printf("10. 退出\n");printf("请选择一个操作:");int result = scanf("%d", &choice);if (result == 1) {switch (choice){case 1:{PerInfo newContact;printf("输入姓名:");scanf("%s", newContact.name);printf("输入性别:");scanf("%s", newContact.gender);printf("输入年龄:");scanf("%d", &newContact.age);printf("输入电话:");scanf("%s", newContact.telephone);printf("输入地址:");scanf("%s", newContact.address);ConPushBack(&myContacts, newContact);break;}case 2:{PerInfo newContact;printf("输入姓名:");scanf("%s", newContact.name);printf("输入性别:");scanf("%s", newContact.gender);printf("输入年龄:");scanf("%d", &newContact.age);printf("输入电话:");scanf("%s", newContact.telephone);printf("输入地址:");scanf("%s", newContact.address);ConPushFront(&myContacts, newContact);break;}case 3:ConPopBack(&myContacts);break;case 4:ConPopFront(&myContacts);break;case 5:ConDisplayAll(&myContacts);break;case 6:ConSave(&myContacts, "contacts.csv");break;case 7:ConLoad(&myContacts, "contacts.csv");break;case 8:printf("请输入要修改的联系人索引:");scanf("%d", &index);// 此处你需要一种方法来获取新的联系人信息// 可以是一个函数,或者直接在这里收集printf("输入新的姓名:");scanf("%s", contact.name);printf("输入新的性别:");scanf("%s", contact.gender);printf("输入新的年龄:");scanf("%d", &contact.age);printf("输入新的电话:");scanf("%s", contact.telephone);printf("输入新的地址:");scanf("%s", contact.address);// 在修改之前确保索引是有效的if (index >= 0 && index < myContacts.size) {ConModify(&myContacts, index, contact);}else {printf("无效的索引。\n");}break;case 9:printf("请输入要查找的联系人姓名:");scanf("%s", targetName);ConSearch(&myContacts, targetName);break;case 10:ConDestroy(&myContacts);printf("退出程序。\n");return 0;default:printf("无效选项,请重新选择。\n");}}else{// 读取失败,清理输入流while (getchar() != '\n'); // 读取并丢弃直到一个新行printf("输入无效,请输入一个数字。\n");}}return 0;
}

contact.c文件

#define _CRT_SECURE_NO_WARNINGS 1
#include "Contact.h"
//通讯录的初始化
void ConInit(Con* ps)
{assert(ps);ps->arr = NULL;ps->size = 0;ps->capacity = 0;
}//通讯录的扩容
void ConCheckcapacity(Con* ps)
{if (ps->size == ps->capacity){assert(ps);int newcapacity = ps->capacity == 0 ? INIT_CAPACITY : ps->capacity * 2;PerInfo* temp = (PerInfo*)realloc(ps->arr, newcapacity * sizeof(PerInfo));if (temp == NULL){perror("realloc:");exit(1);}else{ps->arr = temp;ps->capacity = newcapacity;}}
}//通讯录的销毁
void ConDestroy(Con* ps)
{assert(ps);free(ps->arr);ps->arr = NULL;ps->capacity = 0;ps->size = 0;
}//添加联系人信息到第一个位置
void ConPushFront(Con* ps, PerInfo newContact)
{assert(ps);ConCheckcapacity(ps);for (int i = ps->size - 1;i >= 0;i--){ps->arr[i + 1] = ps->arr[i];}ps->arr[0] = newContact;ps->size++;
}//添加联系人信息到最后一个位置
void ConPushBack(Con* ps, PerInfo newContact)
{assert(ps);ConCheckcapacity(ps);ps->arr[ps->size] = newContact;ps->size++;
}//删除第一个联系人信息
void ConPopFront(Con* ps)
{assert(ps);if (ps->size == 0) {printf("提示:这个联系人列表是空的,没有东西可以删除\n");return;}else{for (int i = 0;i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;}printf("提示:第一个联系人删除成功\n");
}//删除最后一个联系人信息
void ConPopBack(Con* ps)
{assert(ps);  // 确保通讯录指针不为空if (ps->size == 0) {printf("提示:通讯录为空,没有可以删除的联系人\n");return;}ps->size--;  // 减少通讯录的大小,移除最后一个元素printf("提示:最后一个联系人已成功删除\n");
}//修改指定联系人的信息
void ConModify(Con* ps, int index, PerInfo updatedContact)
{assert(ps);if (index < 0 || index >= ps->size) {printf("输入的索引无效,无法修改联系人信息。\n");return;}// 更新指定索引处的联系人信息ps->arr[index] = updatedContact;//将新的联系人信息 updatedContact 赋值给 arr 数组的第 index 个位置。这个操作实质上是一个结构体赋值操作,它将 updatedContact 结构体的所有成员(包括姓名、性别、年龄、电话号码和地址等)复制到 arr[index] 所指向的结构体中。这意味着原来存储在该索引位置的联系人信息会被完全替换为新提供的信息。printf("联系人信息已成功更新:%s %s %d %s %s\n", updatedContact.name, updatedContact.gender, updatedContact.age, updatedContact.telephone, updatedContact.address);
}//查找指定联系人的信息
void ConSearch(Con* ps, const char* targetName)
{assert(ps);  // 确保通讯录指针不为空int found = 0;  // 用于记录是否找到联系人for (int i = 0; i < ps->size; i++) {if (strcmp(ps->arr[i].name, targetName) == 0) {printf("找到联系人: 姓名:%s, 性别:%s, 年龄:%d, 电话:%s, 地址:%s\n",ps->arr[i].name, ps->arr[i].gender, ps->arr[i].age,ps->arr[i].telephone, ps->arr[i].address);found = 1;  // 标记为找到}}if (!found) {printf("未找到联系人:%s\n", targetName);}
}// 打印所有联系人信息
void ConDisplayAll(Con * ps)
{assert(ps);  // 确保通讯录指针不为空if (ps->size == 0) {printf("通讯录为空,没有联系人信息可显示。\n");return;}printf("通讯录包含以下联系人:\n");for (int i = 0; i < ps->size; i++) {printf("%d. 姓名:%s, 性别:%s, 年龄:%d, 电话:%s, 地址:%s\n",i + 1,ps->arr[i].name,ps->arr[i].gender,ps->arr[i].age,ps->arr[i].telephone,ps->arr[i].address);}
}// 保存所有联系人信息到文件
void ConSave(Con* ps, const char* filename)
{assert(ps);  // 确保通讯录指针不为空FILE* file = fopen(filename, "w");  // 打开文件用于写入if (file == NULL) {perror("无法打开文件");return;}// 写入通讯录大小,可用于加载数据fprintf(file, "%d\n", ps->size);for (int i = 0; i < ps->size; i++) {fprintf(file, "%s,%s,%d,%s,%s\n",ps->arr[i].name,ps->arr[i].gender,ps->arr[i].age,ps->arr[i].telephone,ps->arr[i].address);}fclose(file);  // 关闭文件printf("通讯录已成功保存到文件:%s\n", filename);
}// 加载通讯录数据
void ConLoad(Con* ps, const char* filename)
{assert(ps);FILE* file = fopen(filename, "r");if (file == NULL) {perror("无法打开文件");return;}int size;fscanf(file, "%d\n", &size);  // 读取通讯录大小for (int i = 0; i < size; i++) {PerInfo info;fscanf(file, "%[^,],%[^,],%d,%[^,],%[^\n]\n",info.name,info.gender,&info.age,info.telephone,info.address);ConPushBack(ps, info);  // 将读取的信息添加到通讯录}fclose(file);printf("通讯录数据已从文件:%s 加载完成\n", filename);
}

contact.h文件

#pragma once#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 12
#define ADDR_MAX 100
#define INIT_CAPACITY 4typedef struct PersonInfo {char name[NAME_MAX];char gender[SEX_MAX];int age;char telephone[TEL_MAX];char address[ADDR_MAX];
} PerInfo;typedef struct Contact {PerInfo* arr;int size;int capacity;
} Con;// Function declarations
void ConInit(Con* ps);
void ConCheckcapacity(Con* ps);
void ConDestory(Con* ps);
void ConPushFront(Con* ps, PerInfo newContact);
void ConPushBack(Con* ps, PerInfo newContact);
void ConPopFront(Con* ps);
void ConPopBack(Con* ps);
void ConModify(Con* ps, int index, PerInfo updatedContact);
void ConSearch(Con* ps, const char* targetName);
void ConDisplayAll(Con* ps);
void ConSave(Con* ps, const char* filename);
void ConLoad(Con* ps, const char* filename);

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

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

相关文章

Linux下的UDEV机制/守护进程

一. Udev机制概念引入 ( 需要在 etc/udev/rules.d/ 下创建设备的相关规则&#xff0c;不然有可能udev机制生成的设备文件不具备可读可写的权限&#xff0c;adb无法成功通过该设备文件访问设备 ) a. 创建文件夹 sudo vim Xiaomi-audroid.rules b. 添加规则 …

景区ar导览实景导航小程序系统开发源码搭建

开发景区AR导览实景导航小程序系统需要以下步骤&#xff1a; 1. 确定需求和功能&#xff1a;根据景区AR导览实景导航的需求和功能&#xff0c;确定需要开发哪些功能模块&#xff0c;如AR实景导航、语音讲解、景点介绍、路线规划等。 2. 确定技术方案&#xff1a;选择适合的技…

在vscode上面进行分支merge的记录

前言&#xff1a;在我们的项目中&#xff0c;有两个分支&#xff1a;master和liutielong。现在要将liutielong分支的改动merge到master分支中。 如果master分支已经更改了&#xff0c;所以要先pull&#xff08;这是在git bash里面的命令&#xff09;。 git pull origin master…

5分钟——快速搭建后端springboot项目

5分钟——快速搭建后端springboot项目 1. idea新建工程2. 构建pom.xml文件3. 构建application.yml配置文件4. 构建springboot启动类5. 补充增删改查代码6. 运行代码 1. idea新建工程 点击右上角新建一个代码工程 别的地方不太一样也不用太担心&#xff0c;先创建一个工程就好…

学习配置文件

1.yml的语法格式问题&#xff1a; 2.配置文件获取数据&#xff1a; Value方式&#xff1a; Environment&#xff1a; 获取自定义对象的方式&#xff1a; 设置get和set方法&#xff0c;还有toString方法。 3. 日志配置&#xff1a; logo的配置&#xff1a; 日志插件&#xff…

汽车纵染压制专用液压机比例阀放大器

汽车纵染压制专用液压机比例阀放大器是一种专门用于汽车纵梁拉伸工艺的设备&#xff0c;它也可以用于其他金属薄板的压制成型及校正工艺。该类型的液压机通常具备独立的动力机构和电气系统&#xff0c;采用PLC技术进行控制&#xff0c;以确保操作的准确性和稳定性。除了纵梁拉伸…

【iOS】分类,扩展与关联对象

文章目录 前言一、分类实现原理二、分类加载流程三、扩展四、类别与类扩展的区别五、关联对象动态添加取值移除关联对象应用 总结 前言 上一篇章我们探究了类与对象的底层&#xff0c;这一篇我们探究一下分类&#xff0c;扩展与关联对象 一、分类实现原理 首先我们知道扩展是…

Rust :快速了解 VecDeque 双向队列

VecDeque是Rust标准库中的一个双端队列&#xff08;double-ended queue&#xff09;实现&#xff0c;它提供了在队列两端进行高效插入和删除操作的能力。双端队列是一种具有队列和栈的性质的数据结构&#xff0c;元素可以从两端弹出&#xff0c;其限定插入和删除操作在表的两端…

CentOS-7安装grafana

一、通用设置&#xff08;分别在4台虚拟机设置&#xff09; 1、配置主机名 hostnamectl set-hostname --static 主机名2、修改hosts文件 vim /etc/hosts 输入&#xff1a; 192.168.15.129 master 192.168.15.133 node1 192.168.15.134 node2 192.168.15.136 node33、 保持服…

GaussianEditor:快速可控的3D编辑与高斯飞溅

GaussianEditor: Swift and Controllable 3D Editing with Gaussian Splatting GaussianEditor&#xff1a;快速可控的3D编辑与高斯飞溅 Yiwen Chen*​1,2   Zilong Chen*​3,5   Chi Zhang2   Feng Wang3   Xiaofeng Yang2 陈怡雯 *​1,2 陈子龙 *​3,5 张驰 2 王峰 3 杨晓…

MySQL学习笔记7——视图和存储过程

视图和存储过程 一、视图1、视图的作用2、如何操作视图和视图中的数据3、视图的优缺点 二、存储过程1、如何创建存储过程2、调用存储过程3、修改和删除存储过程 一、视图 1、视图的作用 视图是一种虚拟表&#xff0c;我们可以把一段查询语句作为视图存储在数据库中&#xff0…

Cocos Creator 场景树与组件实例查找详解

前言 Cocos Creator 是一款由 Cocos-BCX 团队开发的一款基于 JavaScript 的游戏开发引擎&#xff0c;它提供了一套完整的游戏开发工具和资源&#xff0c;方便开发者快速构建游戏。在 Cocos Creator 中&#xff0c;场景树和组件实例的查找是非常重要的&#xff0c;它们可以帮助开…

.NET Core 中的 ORM 框架对比

在 .NET Core 中选择正确的对象关系映射 &#xff08;ORM&#xff09; 工具可能是开发生命周期中的关键决策。所选的 ORM 会影响应用程序的性能、可维护性和可伸缩性。在本文中&#xff0c;我们将深入分析三个突出的 ORM 选择&#xff1a;Entity Framework Core、Dapper 和 NHi…

算法设计与优化——向量中数据唯一化

0.概述 很多应用中&#xff0c;在进一步处理之前都要求数据元素互异。以网络搜索引擎为例&#xff0c;多个计算节点各自获得的局部搜索结果&#xff0c;需首先剔除其中重复的项目&#xff0c;方可合并为一份完整的报告。类似地&#xff0c;所谓向量的唯一化处理&#xff0c;就…

liqo学习及安装,k8s,kubernetes多集群互联

先按照官方的教程在虚拟机安装学习 在开始以下教程之前&#xff0c;您应该确保您的系统上安装了以下软件&#xff1a; Docker&#xff0c;容器运行时。Kubectl&#xff0c;Kubernetes 的命令行工具。 curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.…

本地有一个face.txt文档,里面是50条url图片链接。怎么通过python做数据增强,还额外再生成200张!!!???

为了完成这个作业&#xff0c;我们需要编写一个Python脚本&#xff0c;该脚本将读取face.txt文件中的图片链接&#xff0c;并对这些链接进行处理&#xff0c;生成额外的图片链接作为数据增强。请注意&#xff0c;由于我们实际上没有真正的图像数据&#xff0c;而是只有URL链接&…

python笔记-检测时间数据递增正确性

概述 本文主要描述了使用一个python脚本检查输入的时间数据&#xff0c;是否按正常递增的格式增加。 背景 在平常写时间校准算法的过程中&#xff0c;输出的数据不好检查是否每个时刻数据都是正确的&#xff0c;所以需要写一个脚本来检查&#xff0c;时间校准算法输出的时间…

基于Python利用zhconv模块进行简繁体字转换

在处理中文文本时&#xff0c;简繁体字之间的转换是一项常见的任务。Python提供了许多库来实现这个目的&#xff0c;其中之一就是zhconv。zhconv是一个Python库&#xff0c;提供了简体字和繁体字之间的转换功能。本教程将向你展示如何使用zhconv模块来实现简繁体字的互转&#…

Redis底层数据结构之Dict

目录 一、概述二、Dict结构三、Dictht结构四、DictEntry结构五、核心特性 上一篇文章 reids底层数据结构之quicklist 一、概述 Redis 的 Dict 是一个高效的键值对映射数据结构&#xff0c;采用双哈希表实现以支持无锁的渐进式 Rehash&#xff0c;确保扩容或缩容时的高效性能。…

想冲宇宙厂,直接挂了。。。

宇宙厂实际是字节&#xff0c;这个称呼是因为字节跳动主宰了宇宙内一切App&#xff0c;有点家大业大的意思。 今天分享一位字节春招凉经&#xff0c;问了一些数据库和Java八股&#xff0c;没出算法题&#xff0c;直接挂了&#xff0c;竟然最喜欢出算法题的字节&#xff0c;这次…