当前位置: 首页 > news >正文

C语言实现通讯录项目

一、通讯录功能

        实现一个可以存放100个人的信息的通讯录(这里采用静态版本),每个人的信息有姓名、性别、年龄、电话、地址等。

        通讯录可以执行的操作有添加联系人信息、删除指定联系人、查找指定联系人信息、修改指定联系人信息、显示联系人信息、根据联系人的某些信息(年龄、姓名、电话等)对联系人进行排序等。

二、代码

1、测试文件(test.c)

#include "contact.h"
int main()
{int input = 0;Contact con;//创建一个通讯录对象,内部可以存放100个人的信息ConInit(&con);//初始化通讯录,一定不能放在循环内部do{int (*p[])(Contact*) = { Add, Del, Search, Modify, Show, Sort };menu();printf("请选择:");scanf("%d", &input);if (input >= 1 && input <= 6)p[input - 1](&con);else if (input == 0)printf("退出通讯录\n");elseprintf("输入错误,请重新输入0~6之间的整数\n");} while (input);return 0;
}

2、通讯录具体实现(contact.c)

#include "contact.h"
//菜单
void menu()
{printf("************************************\n");printf("***** 1. add         2. del    *****\n");printf("***** 3. search      4. modify *****\n");printf("***** 5. show        6. sort   *****\n");printf("***** 0. exit                  *****\n");printf("************************************\n");
}//初始化通讯录
void ConInit(Contact* pc)
{assert(pc);pc->count = 0;memset(pc->data, 0, sizeof(pc->data));
}//查找指定联系人
int FindByName(Contact* pc, char name[])
{for (int i = 0; i < pc->count; i++)if (0 == strcmp(name, pc->data[i].name))return i;//找到了返回下标return -1;//没找到返回-1
}//打印联系人信息
void Print(Contact* pc, int i)
{printf("    %-10s  %-10s  %-10s  %-10s     %-10s\n",pc->data[i].name,pc->data[i].sex,pc->data[i].age,pc->data[i].phone,pc->data[i].address);
}//删除、查找、修改公共信息
int PubInfor(Contact* pc, int n)
{char name[NAME] = { 0 };const char* arr[] = {"", "", "删除", "查找", "修改"};//用2个空字符串占位int pos = 0;while (1){printf("请输入要%s联系人姓名:", (DEL == n) ? arr[DEL] : ((SEARCH == n) ? arr[SEARCH] : arr[MODIFY]));scanf("%s", name);pos = FindByName(pc, name);if (-1 == pos)printf("待%s联系人的信息不存在\n", (DEL == n) ? arr[DEL] : ((SEARCH == n) ? arr[SEARCH] : arr[MODIFY]));elsebreak;}return pos;
}//录入信息
void EnterInfor(Contact* pc, int x)
{int num = -1;const char* arr[] = { "姓名", "性别", "年龄", "电话", "地址" };char* pch[] = { pc->data[x].name, pc->data[x].sex, pc->data[x].age, pc->data[x].phone, pc->data[x].address };while (1){num++;printf("请输入%s:", arr[num]);scanf("%s", pch[num]);if (4 == num)break;}
}//添加联系人信息
void Add(Contact* pc)
{assert(pc && (pc->count <= CON));//通讯录满,不能增加,空指针不能增加EnterInfor(pc, pc->count);pc->count++;printf("添加成功\n");Show(pc);
}//删除指定联系人
void Del(Contact* pc)
{assert(pc && (pc->count != 0));//空通讯录不能删int pos = PubInfor(pc, DEL);for (int i = pos; i < pc->count - 1; i++)pc->data[i] = pc->data[i + 1];pc->count--;printf("删除成功\n");Show(pc);
}//查找指定联系人信息
void Search(Contact* pc)
{assert(pc && (pc->count != 0));int pos = PubInfor(pc, SEARCH);printf("该联系人的信息如下\n");printf("    %-10s  %-10s  %-10s  %-10s      %-10s\n", "姓名", "性别", "年龄", "电话", "地址");Print(pc, pos);
}//修改指定联系人信息
void Modify(Contact* pc)
{assert(pc && (pc->count != 0));int pos = PubInfor(pc, MODIFY);printf("该联系人的信息如下\n");printf("    %-10s  %-10s  %-10s  %-10s      %-10s\n", "姓名", "性别", "年龄", "电话", "地址");Print(pc, pos);printf("请输入修改后的信息\n");EnterInfor(pc, pos);printf("修改成功\n");Show(pc);
}//显示联系人信息
void Show(const Contact* pc)
{assert(pc);printf("                         通讯录联系人的信息如下                         \n");printf("    %-10s  %-10s  %-10s  %-10s      %-10s\n", "姓名", "性别", "年龄", "电话", "地址");for (int i = 0; i < pc->count; i++)Print(pc, i);
}//qsort()函数姓名比较基准
int CmpByName(const void* s1, const void* s2)
{return strcmp(((People*)s1)->name, ((People*)s2)->name);
}//qsort()函数性别比较基准
int CmpBySex(const void* s1, const void* s2)
{return strcmp(((People*)s1)->sex, ((People*)s2)->sex);
}//qsort()函数年龄比较基准
int CmpByAge(const void* s1, const void* s2)
{return strcmp(((People*)s1)->age, ((People*)s2)->age);
}//qsort()函数电话比较基准
int CmpByPhone(const void* s1, const void* s2)
{return strcmp(((People*)s1)->phone, ((People*)s2)->phone);
}//qsort()函数地址比较基准
int CmpByAddress(const void* s1, const void* s2)
{return strcmp(((People*)s1)->address, ((People*)s2)->address);
}//根据联系人信息对联系人进行排序
void Sort(Contact* pc)
{assert(pc && (pc->count != 0));printf("*********************************\n");printf("***** 1. name      2. sex   *****\n");printf("***** 3. age       4. phone *****\n");printf("***** 5. address   0. exit  *****\n");printf("*********************************\n");int input = 0;do{int (*p[])(const void*, const void*) = { CmpByName, CmpBySex, CmpByAge, CmpByPhone, CmpByAddress };printf("请选择排序基准:");scanf("%d", &input);if (input >= 1 && input <= 5){qsort(pc->data, pc->count, sizeof(People), *(p)[input - 1]);break;}else if (0 == input)printf("退出排序\n");elseprintf("输入错误,请重新输入0~5之间的整数\n");} while (input);if (input != 0){const char* arr[] = { "姓名", "性别", "年龄", "电话", "地址" };printf("按照%s排序成功\n", arr[input - 1]);Show(pc);}
}

3、头文件(contact.h)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>#define NAME 20
#define SEX 5
#define AGE 3
#define PHONE 12
#define ADDRESS 30
#define CON 100enum CONTACT
{EXIT, ADD, DEL, SEARCH, MODIFY, SHOW, SORT
};typedef struct People
{char name[NAME];       //姓名char sex[SEX];         //性别char age[AGE];         //年龄char phone[PHONE];     //电话char address[ADDRESS]; //地址
}People;typedef struct Contact
{People data[CON];  //创建一个可以存储信息的结构体数组size_t count;      //count记录通讯录中的人员个数
}Contact;void menu();//菜单
void ConInit(Contact* pc);//初始化通讯录
int FindByName(Contact* pc, char name[]);//查找指定联系人
void Print(Contact* pc, int i);//打印联系人信息
int PubInfor(Contact* pc, int n);//删除、查找、修改公共信息
void EnterInfor(Contact* pc, int x);//录入信息
void Add(Contact* pc);//添加联系人信息
void Del(Contact* pc);//删除指定联系人
void Search(Contact* pc);//查找指定联系人信息
void Modify(Contact* pc);//修改指定联系人信息
void Show(const Contact* pc);//显示联系人信息
int CmpByName(const void* s1, const void* s2);//qsort()函数姓名比较基准
int CmpBySex(const void* s1, const void* s2);//qsort()函数性别比较基准
int CmpByAge(const void* s1, const void* s2);//qsort()函数年龄比较基准
int CmpByPhone(const void* s1, const void* s2);//qsort()函数电话比较基准
int CmpByAddress(const void* s1, const void* s2);//qsort()函数地址比较基准
void Sort(Contact* pc);//根据联系人信息对联系人进行排序

相关文章:

C语言实现通讯录项目

一、通讯录功能 实现一个可以存放100个人的信息的通讯录&#xff08;这里采用静态版本&#xff09;&#xff0c;每个人的信息有姓名、性别、年龄、电话、地址等。 通讯录可以执行的操作有添加联系人信息、删除指定联系人、查找指定联系人信息、修改指定联系人信息、显示联系人信…...

Effective Java读书笔记 draft

一、创建和销毁对象 1、静态工厂方法代替构造器 class Person{//构造器public Person(){}//静态工厂方法public static Person getInstance(){return new Person();} } 优势&#xff1a;1、有名字&#xff0c;代码更容易阅读理解&#xff1b;2、不用每次被调用时都创建新对…...

DeepSeek 助力 Vue 开发:打造丝滑的滑块(Slider)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…...

wordpress使用CorePress主题设置项总结

宝塔面板设置 软件商店中安装的软件有&#xff1a;&#xff08;宝塔网站加速3.1&#xff09;&#xff08;Nginx 1.18.0&#xff09;&#xff08;MySql 5.6.50&#xff09;&#xff08;PHP-5.6&#xff09;&#xff08;phpMyAdmin 4.4&#xff09;&#xff08;Python项目管理器 …...

逆向pyinstaller打包的exe软件,获取python源码(6)

在ailx10&#xff1a;逆向pyinstaller打包的exe软件&#xff0c;获取python源码(3)中&#xff0c;我们逆向出了主程序&#xff0c;但是对其依赖的其他python文件并没有给出逆向方法&#xff0c;实际上非常简单&#xff0c;在PYZ-00.pyz_extracted 文件夹中&#xff0c;只要逆向…...

蓝桥杯 五子棋对弈

五子棋对弈 问题描述 “在五子棋的对弈中&#xff0c;友谊的小船说翻就翻&#xff1f;” 不&#xff01;对小蓝和小桥来说&#xff0c;五子棋不仅是棋盘上的较量&#xff0c;更是心与心之间的沟通。这两位挚友秉承着"友谊第一&#xff0c;比赛第二"的宗旨&#xff…...

【单片机】MSP430MSP432入门

文章目录 0 前言1 开发方式选择2 CCS和开发相关软件3 Keil开发MSP4324 IAR for 430开发MSP4305 总结 0 前言 最近因为想学DSP&#xff0c;所以把之前卸载的CCS给装回来了&#xff0c;手头也还有之前电赛剩下的MSP430和MSP432的板子&#xff0c;由于年代久远&#xff0c;想着花点…...

货车一键启动无钥匙进入手机远程启动的正确使用方法

一、移动管家货车无钥匙进入系统的使用方法 基本原理&#xff1a;无钥匙进入系统通常采用RFID无线射频技术和车辆身份识别码识别系统。车钥匙需要随身携带&#xff0c;当车钥匙靠近货车时&#xff0c;它会自动与货车的解码器匹配。开门操作&#xff1a;当靠近货车后&#xff0…...

自学c++之类、对象、封装

class 类名{int a;//属性 public://权限操作&#xff1b; } 1、权限 public(公共权限&#xff09;类内可以访问&#xff0c;类外可以访问protected&#xff08;保护权限&#xff09;类内可以访问&#xff0c;类外不可以访问&#xff08;儿子可以访问父亲中的保护内容&#xf…...

在VSCode中安装jupyter跑.ipynb格式文件

个人用vs用的较多&#xff0c;不习惯在浏览器单独打开jupyter&#xff0c;看着不舒服&#xff0c;直接上教程。 1、在你的环境中pip install ipykernel 2、在vscode的插件中安装jupyter扩展 3、安装扩展后&#xff0c;打开一个ipynb文件&#xff0c;并且在页面右上角配置内核 …...

SQL_优化

1 SQL优化 (1) 数据读取 ①分区裁剪:使用时只读取需要的分区. ②列裁剪:读取操作(select、where、join、group by、sort by等),不读取不需要的列,减少IO消耗. (2) 数据筛选 ①分区先过滤,区分度大的字段先过滤. ②不在筛选字段上使用函数和表达式. (3) 分组聚合 ①使用窗口函数…...

Neo4j使用neo4j-admin导入csv数据方法

在neo4j desktop里创建project&#xff0c;创建dbms&#xff0c;创建database。 将csv文件放入如下import路径中&#xff0c;然后就可以使用相对路径来使用csv了。 在neo4j desktop中打开Terminal 键入导入数据语句&#xff1a; neo4j-admin database import full --nodes&qu…...

Node.js 登录鉴权

目录 Session express-session 配置 express-session 函数 ts 要配置声明文件 express-session.d.ts express-session 使用 express-session 带角色 Token 什么是 JWT token jsonwebtoken 使用 jsonwebtoken 带角色 Session express 使用 express-session 管理会话&…...

内存泄漏指什么?常见的内存泄漏有哪些?

内存泄漏是指程序在运行过程中&#xff0c;由于某些原因导致程序无法释放已经不再使用的内存&#xff0c;使得这部分内存持续被占用&#xff0c;最终可能导致系统可用内存逐渐减少&#xff0c;严重时会影响系统性能甚至导致程序崩溃。&#xff08;内存泄漏是指程序中已经分配的…...

【PromptCoder】使用 package.json 生成 cursorrules

【PromptCoder】使用 package.json 生成 cursorrules 在当今快节奏的开发世界中&#xff0c;效率和准确性至关重要。开发者们不断寻找能够优化工作流程、帮助他们更快编写高质量代码的工具。Cursor 作为一款 AI 驱动的代码编辑器&#xff0c;正在彻底改变我们的编程方式。但如…...

STM32的C语言软件延时函数

STM32的延时方法很多&#xff0c;其中采用定时器延时&#xff0c;可以得到较为精确的延时&#xff0c;但是有时对延时精度要求不高的场合&#xff0c;采用软件延时&#xff0c;也是必须的。特别是在RTOS系统中&#xff0c;使用SysTick的普通计数模式对延迟进行管理&#xff0c;…...

【洛谷排序算法】P1012拼数-详细讲解

洛谷 P1012 拼数这道题本身并非单纯考察某种经典排序算法&#xff08;如冒泡排序、选择排序、插入排序、快速排序、归并排序等&#xff09;的实现&#xff0c;而是在排序的基础上&#xff0c;自定义了排序的比较规则&#xff0c;属于自定义排序类型的题目。不过它借助了标准库中…...

在WINDOWS系统使用CMake gui编译NLopt配合VSCode使用

1. 准备工作 安装CMake&#xff1a;从CMake官网下载并安装CMake。下载Nlopt源码&#xff1a;从Nlopt官网或GitHub仓库下载Nlopt源码。安装编译器&#xff1a;确保已安装Visual Studio或其他支持的编译器&#xff08;如MinGW&#xff09;。 2. 配置CMake 方式1 打开CMake GU…...

angular生命周期

ngOnChanges&#xff1a;当组件的输入属性&#xff08;Input&#xff09;发生变化时调用。 ngOnInit&#xff1a;在组件的输入属性初始化后调用&#xff0c;但此时视图尚未加载。 ngAfterContentInit&#xff1a;在组件的内容投影&#xff08;ng-content&#xff09;初始化后…...

[AI概念域] AI 大模型是如何被训练出来的?(通俗解读)

说明&#xff1a;这里使用 学生成长五部曲 比喻带你理解大模型如何从零开始学会思考。 AI大模型的训练过程可分为四个核心阶段&#xff1a; 首先进行海量数据收集与清洗&#xff0c;如同为“学生”准备涵盖各领域知识的教材库&#xff1b;接着通过预训练让模型完成“填空题”…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频

使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

系统设计 --- MongoDB亿级数据查询优化策略

系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log&#xff0c;共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题&#xff0c;不能使用ELK只能使用…...