【详解】通讯录项目

目录

通讯录项目要求:

引言:

步骤如下:

用户的数据类型:

初始化循序表:

菜单:

添加联系人:

删除联系人:

修改联系人:

查找联系人:

查看通讯录:

头文件:

(1)Contact.h

(2)Seqlist.h

.c文件

(1)Contact.c

(2)Contest.c

(3)SeqList.c

结语:


通讯录项目要求:

c语言基础要求:结构体,动态内存管理,循序表

通讯录功能要求:

(1)至少能够存储100个人的通讯信息

(2)能够保存用户信息:名字,性别,年龄,电话,地址等

(3)增加联系人

(4)查找指定联系人

(5)删除指定联系人

(6)修改指定联系人

(7)显示联系人信息

引言:

随着c语言结构体和顺序表的逐渐学习深入,我们就可以完成一个通讯录的小项目,通过实现它来检查自己的学习情况和查缺补漏。👏👏👏

步骤如下:

说明:由于通讯录是由循序表的基本运算构成的,故下面的各种操作都只给出在顺序表基础上的完成的,在文章最后会给出循序表的基本运算。

基本运算的函数名如下:

void SLInit(SL* ps) 初始化

void SLDestroy(SL* ps) 销毁

void SLPrint(SL* ps) 打印

void SLCheckCapacity(SL* ps) 扩容

void SLPushBack(SL* ps, ElemType x)尾插

void SLInsert(SL* ps, int pos, ElemType x)指定插入

void SLErase(SL* ps, int pos)删除指定数据

用户的数据类型:

//用户数据
typedef struct PersonInfo
{char name[NAME_MAX];char sex[SEX_MAX];int age;char number[TEL_MAX];char address[ADDR_MAX];
}PeoInfo;

初始化循序表:

基本运算如上面给出的。

void InitContact(contact* con)
{SLInit(con);
}

菜单:

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

效果如下:

添加联系人:

peoinfo是自定义的数据结构

void AddContact(contact* con)
{PeoInfo e;printf("请输入联系人姓名\n");scanf("%s", e.name);printf("请输入联系人年龄\n");scanf("%d", &e.age);printf("请输入联系人性别\n");scanf("%s", e.sex);printf("请输入联系人电话\n");scanf("%s", e.number);printf("请输入联系人住址\n");scanf("%s", e.address);SLPushBack(con, e);
}

运行结果如下:

删除联系人:

用一个name数组来存储输入的字符串,和通讯录对比若findindex大于0说明该联系人存在删除成功,若小于0说明不存在该联系人删除失败。

查找联系人的函数如下:

int FindNAME(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 DelContact(contact* con)
{char name[NAME_MAX];printf("请输入要查找的联系人姓名\n");//char name[NAME_MAX];scanf("%s",name);int findindex = FindNAME(con, name);if (findindex >= 0){SLErase(con, findindex);printf("删除联系人成功\n");}elseprintf("删除联系人失败\n");
}

运行结果如下:

修改联系人:

先查找联系人在进行修改和输入新的联系人,和上面的删除差不多。😊😊😊

void ContactModify(contact*con)
{char name[NAME_MAX];printf("请输入要修改联系人名称\n");scanf("%s", name);int findindex = FindNAME(con, name);if (findindex < 0){printf("无此联系人\n");return;}else{printf("请输入联系人姓名\n");scanf("%s", con->arr[findindex].name);printf("请输入联系人年龄\n");scanf("%d", &con->arr[findindex].age);printf("请输入联系人性别\n");scanf("%s", con->arr[findindex].sex);printf("请输入联系人电话\n");scanf("%s", con->arr[findindex].number);printf("请输入联系人住址\n");scanf("%s", con->arr[findindex].address);printf("修改联系人成功\n");}}

运行结果如下:

查找联系人:

先输入要查找联系人的姓名,后通过FindNAME函数找到联系人对应的下标,进行判断,最后在把联系人对应的信息输出。

void ContactFind(contact* con)
{printf("请输入要查找的姓名\n");char name[NAME_MAX];scanf("%s", name);int findindex = FindNAME(con, name);if (findindex < 0){printf("查无此人\n");return;}else{printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");printf("%s %s %d %s %s\n",con->arr[findindex].name,con->arr[findindex].sex,con->arr[findindex].age,con->arr[findindex].number,con->arr[findindex].address);}}

运行如下:

查看通讯录:

void ShowContact(contact* con)
{printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");for (int i = 0; i < con->size; i++){printf("%s %s %d %s %s\n",con->arr[i].name,con->arr[i].sex,con->arr[i].age,con->arr[i].number,con->arr[i].address);}
}

运行结果如下:

由于是个项目故要进行个功能的函数分装和头文件的引用,故下面我给出头文件和.c文件大家按照我给出的名字在编译器上创建即可运行。

头文件:

(1)Contact.h

声明通讯录的各种函数及结构体内容。

#pragma once
#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 11
#define ADDR_MAX 100//前置声明//用户数据
typedef struct PersonInfo
{char name[NAME_MAX];char sex[SEX_MAX];int age;char number[TEL_MAX];char address[ADDR_MAX];
}PeoInfo;
struct SeqList;
typedef struct SeqList contact;
//初始化通讯录
void InitContact(contact* con);
//添加通讯录数据
void AddContact(contact* con);
//删除通讯录数据
void DelContact(contact* con);
//展示通讯录数据
void ShowContact(contact* con);
//查找通讯录数据
void FindContact(contact* con);
//修改通讯录数据
void ModifyContact(contact* con);
//销毁通讯录数据
void DestroyContact(contact* con);

(2)Seqlist.h

循序表的基本运算

#pragma once
//PeoInfo
#include "Contact.h"
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
typedef PeoInfo ElemType;
typedef struct SeqList
{ElemType* arr;int capacity;int size;
}SL;
//初始化和销毁
void SLInit(SL* ps);
void SLDestroy(SL* ps);
void SLPrint(SL* ps);
//扩容
void SLCheckCapacity(SL* ps);
//头部插入删除 / 尾部插入删除
void SLPushBack(SL* ps, ElemType x);
void SLPopBack(SL* ps);
void SLPushFront(SL* ps, ElemType x);
void SLPopFront(SL* ps);//指定位置之前插入/删除数据
void SLInsert(SL* ps, int pos, ElemType x);
void SLErase(SL* ps, int pos);
//int SLFind(SL* ps, ElemType x);

.c文件

(1)Contact.c

通讯录的函数具体实现。

#define  _CRT_SECURE_NO_WARNINGS 1
#include "Contact.h"
#include "Seqlist.h"
void InitContact(contact* con)
{SLInit(con);
}
void AddContact(contact* con)
{PeoInfo e;printf("请输入联系人姓名\n");scanf("%s", e.name);printf("请输入联系人年龄\n");scanf("%d", &e.age);printf("请输入联系人性别\n");scanf("%s", e.sex);printf("请输入联系人电话\n");scanf("%s", e.number);printf("请输入联系人住址\n");scanf("%s", e.address);SLPushBack(con, e);
}
int FindNAME(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 DelContact(contact* con)
{char name[NAME_MAX];printf("请输入要查找的联系人姓名\n");//char name[NAME_MAX];scanf("%s",name);int findindex = FindNAME(con, name);if (findindex >= 0){SLErase(con, findindex);printf("删除联系人成功\n");}elseprintf("删除联系人失败\n");
}
void ShowContact(contact* con)
{printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");for (int i = 0; i < con->size; i++){printf("%s %s %d %s %s\n",con->arr[i].name,con->arr[i].sex,con->arr[i].age,con->arr[i].number,con->arr[i].address);}
}
void ContactModify(contact*con)
{char name[NAME_MAX];printf("请输入要修改联系人名称\n");scanf("%s", name);int findindex = FindNAME(con, name);if (findindex < 0){printf("无此联系人\n");return;}else{printf("请输入联系人姓名\n");scanf("%s", con->arr[findindex].name);printf("请输入联系人年龄\n");scanf("%d", &con->arr[findindex].age);printf("请输入联系人性别\n");scanf("%s", con->arr[findindex].sex);printf("请输入联系人电话\n");scanf("%s", con->arr[findindex].number);printf("请输入联系人住址\n");scanf("%s", con->arr[findindex].address);printf("修改联系人成功\n");}}
void ContactFind(contact* con)
{printf("请输入要查找的姓名\n");char name[NAME_MAX];scanf("%s", name);int findindex = FindNAME(con, name);if (findindex < 0){printf("查无此人\n");return;}else{printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "住址");printf("%s %s %d %s %s\n",con->arr[findindex].name,con->arr[findindex].sex,con->arr[findindex].age,con->arr[findindex].number,con->arr[findindex].address);}}
void ContactDesTroy(contact* con)
{SLDestroy(con);
}

(2)Contest.c

主函数,将Contact.c里面的函数调用,用一个swich来进行多功能的通讯录,通过do,while的特性先运行一次再判断要不要继续,符合我们日常玩游戏的逻辑,最后不要忘了一定要销毁我们开辟的空间哦。💖💖💖

#define  _CRT_SECURE_NO_WARNINGS 1
#include "Seqlist.h"
void menu()
{printf("********************通讯录******************\n");printf("*********1.添加联系人    2.删除联系人*******\n");printf("*********3.修改联系人    4.查找联系人*******\n");printf("*********5.查看通讯录    0. 退   出  *******\n");printf("********************************************\n");
}
int main()
{contact con;int op=-1;InitContact(&con);do{menu();printf("请选择\n");scanf("%d", &op);switch (op){case 1://添加联系人AddContact(&con);break;case 2:DelContact(&con);break;//删除联系人case 3:ContactModify(&con);break;//修改联系人case 4:ContactFind(&con);break;//查找联系人case 5:ShowContact(&con);break;//查看通讯录case 0:printf("退出程序.....\n");return 0;//退   出default:printf("输入错误,请重新输入\n");break;//}} while (op!=0);ContactDesTroy(&con);return 0;}

(3)SeqList.c

循序表基本运算的实现。

#define  _CRT_SECURE_NO_WARNINGS 1
#include "Seqlist.h"
void SLInit(SL* ps)
{ps->arr = NULL;ps->capacity = ps->size = 0;
}
void SLDestroy(SL* ps)
{free(ps->arr);ps->capacity = ps->size = 0;ps = NULL;
}
void SLPrint(SL* ps)
{for (int i = 0; i < ps->size; i++){printf("%d ", ps->arr[i]);}printf("\n");
}
void SLCheckCapacity(SL* ps)
{if (ps->capacity == ps->size){int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;ElemType* tmp = (ElemType*)realloc(ps->arr, sizeof(ElemType) * newcapacity);if (tmp == NULL){perror("realloc fail!");exit(1);}ps->arr = tmp;ps->capacity = newcapacity;}
}
void SLPushBack(SL* ps, ElemType x)
{assert(ps);SLCheckCapacity(ps);ps->arr[ps->size++] = x;
}
void SLInsert(SL* ps, int pos, ElemType 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] = x;ps->size++;
}
void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);for (int i = pos; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}

易错点:

(1)头文件里面不能再包含头文件,及头文件不能嵌套。

(2)对应使用c语言的库函数一定要将对应的头文件带上(如realloc要加上#include <stdlib.h>),不带的话运行就会出错,代码一多还很难找到,编译器的提示也不是很准确,故建议大家一用到上面库函数一定要把头文件马上写上不要等到最后再来(会忘掉)。

(3)前置声明,因为头文件的引用不能嵌套,故要想引用别的头文件的内容可以进行前置声明例如:

结语:

其实写博客不仅仅是为了教大家,同时这也有利于我巩固自己的知识点,和一个学习的总结,由于作者水平有限,对文章有任何问题的还请指出,接受大家的批评,让我改进,如果大家有所收获的话还请不要吝啬你们的点赞收藏和关注,这可以激励我写出更加优秀的文章。

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

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

相关文章

《WebKit 技术内幕》之七(1): 渲染基础

《WebKit 技术内幕》之七&#xff08;1&#xff09;&#xff1a; 渲染基础 WebKit的布局计算使用 RenderObject 树并保存计算结果到 RenderObject 树。 RenderObject 树同其他树&#xff08;如 RenderLayer 树等&#xff09;&#xff0c;构成了 WebKit 渲染的为要基础设施。 1…

【RT-DETR有效改进】Google | EfficientNetV1一种超轻量又高效的网络 (附代码 + 添加教程)

前言 大家好&#xff0c;我是Snu77&#xff0c;这里是RT-DETR有效涨点专栏。 本专栏的内容为根据ultralytics版本的RT-DETR进行改进&#xff0c;内容持续更新&#xff0c;每周更新文章数量3-10篇。 专栏以ResNet18、ResNet50为基础修改版本&#xff0c;同时修改内容也支持Re…

python算法与数据结构---排序和归并排序

学习目标 掌握归并排序的基本原理使用python语言解答归并排序题目 归并排序 原理及过程 将两个有序的数组合并成一个有序数组称为从上往下分解&#xff1a;把当前区间一分为二&#xff0c;直至分解为若干个长度为1的子数组从上往下的合并&#xff1a;两个有序的子区域两两向…

Pytest 测试框架与Allure 测试报告——Allure2测试报告-L1

目录&#xff1a; allure2安装 Allure2介绍Allure2报告展示Allure2报告展示-首页概览Allure2报告展示-用例详情页Allure2安装Allure2下载与安装Allure环境验证插件安装-Python插件安装-Java验证插件安装-Javaallure2运行方式 生成测试报告流程使用Allure2运行方式-Python使用A…

FaFu--练习复盘--3

4、指针的应用 4.1、三角形周长和面积计算程序 描述 已知三角形的三条边的长度&#xff0c;求该三角形的周长和面积&#xff0c;如果三个边不能构成三角形&#xff0c;则三角形的周长和面积都为0。完成程序的编写。 输入 输入1行&#xff0c;包含3个实数&#xff0c;各实数之…

大模型关键技术:上下文学习、思维链、RLHF、参数微调、并行训练、旋转位置编码、模型加速、大模型注意力机制优化、永久记忆、LangChain、知识图谱、多模态

大模型关键技术 大模型综述上下文学习思维链 CoT奖励建模参数微调并行训练模型加速永久记忆&#xff1a;大模型遗忘LangChain知识图谱多模态大模型系统优化AI 绘图幻觉问题从 GPT1 - GPT4 拆解GPTs 对比主流大模型技术点旋转位置编码层归一化激活函数注意力机制优化 大模型综述…

四种方法将 Docker Registry 迁移至 Harbor

Registry Docker Distribution Docker Distribution 是第一个是实现了打包、发布、存储和镜像分发的工具&#xff0c;起到 docker registry 的作用。&#xff08;目前 Distribution 已经捐赠给了 CNCF&#xff09;。其中 Docker Distribution 中的 spec 规范后来也就成为了 O…

在线WebOffce在HTML/VUE/Electron纯前端网页编辑Office之打开Word后自动处于修订模式

在线办公协同办公过程中&#xff0c;对于老板给出的文档修改&#xff0c;如果在错别字方面都要自己一个个字去看的话也太浪费时间了&#xff0c;其实word上就有一个修订模式&#xff0c;可以帮助大家高效完成文档的修改&#xff0c;在线WebOffce在HTML/VUE/Electron纯前端网页编…

Semaphone应用源码分析

Semaphone应用&源码分析 3.1 Semaphore介绍 sync&#xff0c;ReentrantLock是互斥锁&#xff0c;保证一个资源同一时间只允许被一个线程访问 Semaphore&#xff08;信号量&#xff09;保证1个或多个资源可以被指定数量的线程同时访问 底层实现是基于AQS去做的。 Semap…

pinia 的使用方法

使用方式&#xff08;选项式&#xff09; 1、在 mian.js 导入 pinia 里的 createPinia 函数。 2、app.use 这个 createPinia 函数的返回值。 // main.jsimport { createPinia } from pinia;app.use(createPinia()); 3、创建一个 js 文件&#xff08;该文件保存着共享的数据&…

Git和SVN

1、Git Git是一个分布式版本控制系统&#xff0c;由Linus Torvalds创建&#xff0c;用于有效、高速地处理从小到大的项目版本管理。Git是开源的&#xff0c;采取了分布式的版本库的方式&#xff0c;不需要服务器端软件就可以运行。 Git的核心概念 以下是Git中的一些核心概念…

《Python数据分析技术栈》第03章 02 数据结构(Structure of data)

02 数据结构&#xff08;Structure of data&#xff09; 《Python数据分析技术栈》第03章 02 数据结构&#xff08;Structure of data&#xff09; The data that we need to analyze could have any of the following structures, 我们需要分析的数据可能具有以下任何一种结…

RabbitMQ-数据持久化

一、持久化类型 1、交换机持久化&#xff08;SpringAMQP默认&#xff09; 2、队列持久化&#xff08;SpringAMQP默认&#xff09; 3、消息持久化 二、消息持久化 1、纯内存操作 如果采用纯内存操作&#xff0c;那么消息存储达到队列的上限之后&#xff0c;会有一个page ou…

开源进程/任务管理服务Meproc使用之HTTP API

本文讲述如何使用开源进程/任务管理服务Meproc的HTTP API管理整个服务。 Meproc所提供的全部 API 的 URL 都是相同的。 http://ip:port/proc例如 http://127.0.0.1:8606/proc在下面的小节中&#xff0c;我们使用curl命令向您展示 API 的方法、参数和请求正文。 启动任务 …

git 常规操作及设置

git 常规操作及设置 Git是一个分布式版本控制系统&#xff0c;可以用来跟踪文件的修改历史并与其他人进行协作开发。下面是一些常见的Git操作及设置&#xff1a; 初始化仓库&#xff1a;使用命令git init在当前目录创建一个新的Git仓库。 克隆仓库&#xff1a;使用命令git clo…

TCP/IP协议及配置、IP地址、子网掩码、网关地址、DNS与DHCP介绍

一、什么是服务器 能够为其他计算机提供服务的更高级的电脑 尺寸:Unit 1u1.75英寸44.45mm4.445cm IDC&#xff08;机房&#xff09; C/S结构 Client/Server客户端和服务端 二、TCP/IP协议 计算机与计算机之间通信的协议 三要素&#xff1a; IP地址 子网掩码 IP路由 I…

基于一次应用卡死问题所做的前端性能评估与优化尝试

问题背景 在上个月&#xff0c;由于客户反馈客户端卡死现象但我们远程却难以复现此现象&#xff0c;于是我们组织了一次现场上门故障排查&#xff0c;并希望基于此次观察与优化&#xff0c;为客户端开发提供一些整体的优化升级。当然&#xff0c;在尝试过程中&#xff0c;也发…

大模型实战营Day6 作业

基础作业 使用 OpenCompass 评测 InternLM2-Chat-7B 模型在 C-Eval 数据集上的性能 环境配置 conda create --name opencompass --clone/root/share/conda_envs/internlm-base source activate opencompass git clone https://github.com/open-compass/opencompass cd openco…

eMMC之分区管理、总线协议和工作模式

一、eMMC 简介 eMMC 是 embedded MultiMediaCard 的简称。MultiMediaCard&#xff0c;即MMC&#xff0c; 是一种闪存卡&#xff08;Flash Memory Card&#xff09;标准&#xff0c;它定义了 MMC 的架构以及访问 Flash Memory 的接口和协议。而eMMC 则是对 MMC 的一个拓展&…

android 13.0 Camera2 去掉后置摄像头 仅支持前置摄像头功能

1.概述 在定制化13.0系统rom定制化开发中,当产品只有一个前置摄像头单摄像头,这时调用相机时就需要默认打开前置摄像头就需要来看调用摄像头这块的代码,屏蔽掉后置摄像头的调用api就可以了,接下来就来具体实现相关功能的开发 2.Camera2 去掉后置摄像头 仅支持前置摄像头功…