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

news/2024/9/20 1:33:09/ 标签: 数据结构

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.ppmy.cn/news/1433519.html

相关文章

PaddleSeg (2) 模型训练

已处理好数据集和配置文件,可以开始模型训练。 启动训练 python tools/train.py --config configs/xxx.yml --do_eval --use_vdl --save_interval 500 --save_dir output/xxx上述训练命令解释:* `--config`

java spring 07 createBean()和doCreateBean()

01.createBean方法 protected Object createBean(String beanName, RootBeanDefinition mbd, Nullable Object[] args)throws BeanCreationException {if (logger.isTraceEnabled()) {logger.trace("Creating instance of bean " beanName "");}RootBea…

引导过程和服务控制

1、Linux系统开机引导过程 1&#xff09;开机自检 检测硬件设备&#xff0c;找到能够引导系统的设备&#xff0c;比如硬盘 2&#xff09;MBR引导 运行MBR扇区里的主引导程序GRUB 3&#xff09;启动GRUB菜单 系统读取GRUB配置文件(/boot/grub2/grub.cfg)获取内…

spring boot 定义启动页 到 login

当前办法只是针对 项目启动后 直接跳转到 指定静态页面 如果有验证身份 安全等问题 可以另外想办法 去添加 &#xff0c;需要的直接 拉过去使用 修改 【"redirect: 需要启动后访问到文件位置得地址 ”】 直接上代码 &#xff1a; import org.springframework.context…

【教程】使用vitepress搭配githubPages构建自己的在线笔记

1. 创建VitePress项目 确保自己已经安装好了node&#xff0c;我这个笔记用的是node 18.16.0, 怎么安装nvm这个可以csdn或者掘金&#xff0c;再或者等我有空了我就更新一下 使用nvm安装node # 查看可用版本 nvm list avaliable # 安装node nvm install 18.16.0 # 切换node nvm …

(C语言)sscanf 与 sprintf详解

目录 1.sprintf函数详解 2. sscanf函数详解 1.sprintf函数详解 头文件&#xff1a;stdio.h 作用&#xff1a;将格式化的数据写入字符串里&#xff0c;也就是将格式化的数据转变为字符串。 演示&#xff1a; #include <stdio.h> struct S {char name[10];int height;…

无人机探测技术,无人机侦测频谱仪技术实现详解

频谱仪&#xff0c;又称为频谱分析仪&#xff0c;是一种用于测量电信号频谱特性的仪器。其基本原理是通过将时域信号转换为频域信号&#xff0c;进而分析信号的频率成分、功率分布、谐波失真等参数。频谱仪利用快速傅里叶变换&#xff08;FFT&#xff09;算法&#xff0c;将采集…

Github 2024-04-24 C开源项目日报 Top9

根据Github Trendings的统计,今日(2024-04-24统计)共有9个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量C项目9C++项目1我的电视 - 安卓电视直播软件 创建周期:40 天开发语言:CStar数量:649 个Fork数量:124 次关注人数:649 人贡献人数:1 人Open…

STM32 USB HID报告描述符没有报告长度

STM32 USB HID设置(STM32CubeMX)_我也想成大侠的博客-CSDN博客 不影响鼠标功能

面向对象设计模式

设计模式通常被分为三种类型&#xff1a;创建型模式、结构型模式和行为型模式。 创建型模式 创建型模式主要关注对象的创建机制&#xff0c;它们提供了一种将对象创建和实例化的机制&#xff0c;使得系统在不直接依赖于具体类的情况下能够灵活地创建对象。 创建型模式的典型…

力扣---填充每个节点的下一个右侧节点指针 II

给定一个二叉树&#xff1a; struct Node {int val;Node *left;Node *right;Node *next; } 填充它的每个 next 指针&#xff0c;让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点&#xff0c;则将 next 指针设置为 NULL 。 初始状态下&#xff0c;所有 next 指针都…

Prompt Engineering,提示工程

什么是提示工程&#xff1f; 提示工程也叫【指令工程】。 Prompt发送给大模型的指令。比如[讲个笑话]、[用Python编个贪吃蛇游戏]、[给男/女朋友写情书]等看起来简单&#xff0c;但上手简单精通难 [Propmpt]是AGI时代的[编程语言][Propmpt]是AGI时代的[软件工程][提示工程]是…

Spring5深入浅出篇:JDK代理与CGLIB代理区别

Spring5深入浅出篇:JDK代理与CGLIB代理区别 很多粉丝私信我这个Spring5的课程在哪看,这边是在B站免费观看欢迎大家投币支持一下. https://www.bilibili.com/video/BV1hK411Y7zf JDK动态代理与CGLIB的区别 在Java的世界里&#xff0c;动态代理主要有两种实现方式&#xff1a;JDK…

广州大学《虚拟现实与游戏开发》实验报告一HTC-VR环境搭建与开发

广州大学学生实验报告 开课实验室&#xff1a; 学院 年级、专业、班 姓名 学号 实验课程名称 虚拟现实与游戏开发 成绩 实验项目名称 1. HTC-VR环境搭建与开发 指导老师 实验目的 HTC VIVE硬件安装虚拟现实开发环境搭建 3.熟悉虚拟现实硬件系统和…

springboot-异步、定时、邮件任务

目录 一&#xff0c;前言 二&#xff0c;异步 2.1&#xff0c;案例&#xff1a; 1&#xff0c;首先创建一个service&#xff1a; 2&#xff0c;Controller: ① 想办法告诉spring我们的异步方法是异步的&#xff0c;所以要在方法上添加注解 Async ②去springboot主程序中开…

深入Spring Boot配置机制:如何高效管理应用配置

一、属性的优先级和配置文件的位置 在Spring Boot应用中&#xff0c;我们可以在多个地方定义配置属性&#xff0c;并且Spring Boot提供了一套优先级排序&#xff0c;来决定同一属性多处定义时的覆盖关系。理解这个机制对于配置管理至关重要。 1. 配置文件查找的顺序 Spring …

【debug记录】有gpu,但是 pytorch仍显示 cpu【原来是新电脑没安装cuda】

原来是新电脑没安装cuda&#xff0c;以为安装了pytorch包就可以了。 检查过程&#xff1a; nvcc 不是内部或外部命令&#xff0c;也不是可运行的程序, 说明没有安装cuda。 查看电脑显卡最高支持cuda版本&#xff1a;nvidia-smi 安装cuda&#xff0c;选择版本&#xff1a;ht…

基于小程序实现的查寝打卡系统

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】&#xff1a;Java 【框架】&#xff1a;ssm 【…

flink1.18.0 流转表 表转流 jdk17 attachAsDataStream

目的 流表互转 而且流sink 表sink同时存在且都可以输出. 依赖类 package flink.luca.flinkTableAndSQL.Convert;import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;@Data @AllArgsConstructor @NoArgsConstructor public class Outer…

gcc/g++ 的使用

————gcc&#xff1a;只能编译c语言 ————g&#xff1a;c和c都可以编译 当然&#xff0c;c语言编译还是推荐gcc。 在学习gcc/g之前&#xff0c;我们要先了解一些知识点&#xff1a; 一、背景知识 1&#xff0c;预处理 gcc -E就是告诉编译器到预处理阶段就停下来&am…