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

【C++】C++应用案例-通讯录管理系统

目录

一、整体介绍

1.1、需求和目标

1.2、整体功能描述

二、页面及功能描述

2.1 主菜单

2.2 添加联系人菜单

2.3 显示联系人菜单

2.4 修改联系人菜单

2.5 退出功能

三、流程设计

3.1 主流程

3.2 添加操作流程

3.3 显示联系人操作流程

3.4 修改联系人操作流程

四、代码设计

4.1 核心思路

4.2 项目文件分类设计

4.2.1 头文件

4.2.2 源文件

4.2.3 代码实现步骤

4.3 代码具体实现

4.3.1 定义头文件

4.3.2 实现主体流程    

4.3.3 绘制菜单

4.3.4 读取键盘输入

4.3.5 实现具体操作功能


一、整体介绍

1.1、需求和目标

        项目的需求,实现一个叫做“通讯录管理”的基于命令行界面的通讯录管理软件。

        我们的目标,是通过项目练习,初步掌握编写软件的方法和技巧。

1.2、整体功能描述

        这个软件相对简单,只需要基于命令行做纯文本的交互,不涉及图形化界面。作为一个记录通讯录软件,主要有三大功能:添加联系人、显示联系人与修改联系人。也就是说,软件需要能够记录联系人的姓名与联系方式等相关信息,并提供查询显示联系人信息的功能,也可对联系人信息进行修改。而且为了让软件有真正的实用价值,需要对数据做持久保存:我们这里只需要存放在一个指定的文本文件中。

        项目采用分级菜单方式,每一级菜单应该有“返回主菜单”功能;主菜单有“退出”选项。

二、页面及功能描述

2.1 主菜单

        运行软件后首先应该显示主菜单。主菜单提供四个选项:“添加联系人”、“显示联系人”、"修改联系人"和“退出”,并在下方提示用户输入1-4的数字,选择不同的功能。

主菜单界面如下:

2.2 添加联系人菜单

        在主菜单页面选择“1”,可以进入记账菜单(二级菜单)。添加联系人菜单提供三个选项:“办公”、“个人”和“退出”;并在下方提示用户按对应的数字进行功能选择。

记账菜单界面如下:

        在添加联系人菜单页面选择“1”,可以记录一条办公类联系人信息。联系人信息包括:类型(办公/个人)、姓名、电话、住址。这里需要提示用户输入联系人的姓名、电话与住址信息,然后显示完成添加。

        类似地,在联系人菜单页面选择“2”,可以记录一条个人类联系人信息。提示用户输入联系人的姓名、电话与住址,然后显示完成添加。

2.3 显示联系人菜单

        在主菜单页面选择“2”,可以进入显示联系人菜单。显示联系人菜单提供四个选项:“全部”、“办公”、“个人”和“退出”;并在下方提示用户按对应的数字进行功能选择。

显示联系人菜单界面如下:

        在显示联系人菜单页面,选择“1”可以显示全部联系人信息;选择“2”可以显示所有办公类联系人;选择“3”可以显示所有个人类联系人。用户选择之后,除了应该显示对应的联系人信息外,还应该对所有联系人个数进行统计汇总。

        对应地,选择“1”之后列出所有联系人,统计的是通讯录的总条数;选择“2”之后列出所有办公类联系人,统计办公类总条数;选择“3”之后列出所有个人类联系人,统计个人类总条数。

2.4 修改联系人菜单

        在主菜单页面选择“3”,可以进入修改联系人菜单。修改联系人菜单提供三个选项:“办公”、“个人”和“退出”;并在下方提示用户按对应的数字进行功能选择。

显示联系人菜单界面如下:

        在修改联系人菜单页面,选择“1”可以修改办公类别联系人信息;选择“2”可以个人类别联系人信息。用户选择之后,根据提示输入要修改的联系人姓名,如没有找到,提示未找到此人;如找到此联系人,输入更改后的姓名、电话与住址,并提示修改成功。

2.5 退出功能

        在主菜单页面,选择“3”可以退出软件。页面将做确认退出的对话提醒:如果用户输入“Y”则退出,输入“N”则返回主菜单页面。

三、流程设计

3.1 主流程

3.2 添加操作流程

3.3 显示联系人操作流程

3.4 修改联系人操作流程

四、代码设计

4.1 核心思路

        通讯录软件处理的数据,就是添加或者修改的“联系人”。每一条联系人数据,都应该包含类型、姓名、电话、住址四部分,这可以构建一个结构体类型 Person来表示。

        而程序运行的开始,应该读取保存在文件中的数据,读取之后应该是一个 Person类型的数组。

        在流程控制方面,如果用户不选择退出,程序就不会结束,所以应该用一个while循环来处理整个流程;当用户确认退出时,更改一个标志位,用来退出循环。

        每一级菜单做键盘选择后,可以用 switch 分支语句来处理;不同的功能模块,可以包装成函数。

4.2 项目文件分类设计

4.2.1 头文件

        对于一个C++项目来说,构建整体架构很重要的一步就是定义头文件。一般我们会把全局变量、函数声明、以及结构体的定义都放在头文件中。

本项目可以设计两个头文件,来管理不同的内容:

  1. 结构体 Person的定义,以及涉及到账目操作的函数声明,都可以放在一个头文件 person_item.h 中;
  2. 其它一些通用的设置和功能性函数,可以放在另一个头文件common.h 中

4.2.2 源文件

真正的代码实现都放在源文件中。根据不同的用途,项目中可以用四个源文件来实现对应的功能

  1. 主体代码可以放在一个源文件 person_main.cpp 中
  2. 绘制菜单的函数都放在menus.cpp中
  3. 通用函数(比如读取键盘输入)放在read_input.cpp中
  4. 针对账目的所有操作函数(比如记账、查询)全部放在operations.cpp中

4.2.3 代码实现步骤

1、实现整体框架和主题流程

  • 在头文件person_item.h中定义好结构体;在common.h 中定义通用配置
  • 在源文件person_main.cpp的主函数中,参照主流程图实现主体流程

2、填充具体功能

  • 在menus.cpp中定义绘制各级菜单的函数;函数声明放在common.h里
  • 在read_input.cpp中定义读取键盘输入的函数,包括读取菜单选择、读取输入的金额数、读取确认退出信息;这些函数都需要对输入做合法性校验,并返回正确的值;函数声明放在common.h里
  • 在operations.cpp中定义从文件加载数据、记账、查询对应的函数。

3、各功能的细分

1)添加功能

  • 首先需要读取键盘输入的姓名、电话和备住址信息;
  • 然后将其保存在一个Person对象中,并添加到vector,同时写入文件

2)显示功能

  • 需要用for循环遍历整个vector
  • 通过条件筛选需要的联系人打印输出,并统计总和

2)修改功能

  • 需要用for循环遍历整个vector
  • 通过条件匹配到联系人,对数据进行更改
  • 将更改后的数组重新写入文件

4)退出功能

  • 提示用户确认退出
  • 用户确认后,更改循环标志位,退出循环

4.3 代码具体实现

4.3.1 定义头文件

        首先可以在common.h中,引入相应的库,定义出需要的全局变量,以及声明绘制菜单和读取键盘输入的通用函数。通用设置,通用功能性函数声明。

#pragma once
//通用设置,通用功能性函数声明
#include<iostream>			//输入输出
#include<string>			//字符串操作
#include<fstream>			//文件操作
#include<vector>
#include <algorithm>
using namespace std;#define max 1000
#define OFFICE "办公"
#define MYSELF "个人"
#define FILENAME "book.txt"
//绘制菜单函数
void menus_main();
void menus_app();
void menus_show();
void menus_revise();
void menus_delete();//读取键盘输入进行合法性校验的函数
char readMenuSelection(int options);
char readquitconfirm();

        然后在person_item.h定义核心数据结构:结构体 Person,并声明涉及到账目操作的函数。结构体定义,涉及账目操作的函数声明。

#pragma once
//结构体定义,涉及通讯录管理操作的函数声明
#include "common.h"//设计联系人结构体
struct Person
{string PersonItem;	//类别,1、办公,2、个人string name;	//姓名string iphone;	//电话string address;	//单位
};//针对通讯录数据进行操作的函数//加载通讯录数据
void loadDataFromFile(vector<Person>& ps);//添加
void person_add(vector<Person>& ps);
void insertIntoFile(const Person& p);
void person_addmyself(vector<Person>& ps);
void person_addOffice(vector<Person>& ps);
//显示
void person_show(vector<Person>& ps);
void showPerson(const vector<Person>& ps);
void showPerson(const vector<Person>& ps, const string PersonItem);
void printPerson(const Person& p);
//修改
void person_revise(vector<Person>& ps);
void change(vector<Person>& ps, string item);

4.3.2 实现主体流程    

在源文件 person_main.cpp 的主函数中,参照主流程图实现主体流程。

代码如下:

#include "common.h"
#include "person_item.h"int main() {//从文件加载数据vector<Person> ps;loadDataFromFile(ps);bool quit = false;while (!quit){//1、显示主菜单menus_main();//2、读取键盘输入,并做合法性校验char key= readMenuSelection(5);switch (key){case '1':			//1、添加联系人menus_app();	//添加菜单person_add(ps);	//添加功能break;case '2':			//2、显示联系人menus_show();	//显示菜单person_show(ps);		//显示功能break;case '3':			//3、修改联系人menus_revise();	//修改菜单person_revise(ps);	//修改功能break;case '4':			//退出cout << "确认退出? (Y/N)";if (readquitconfirm() == 'Y')quit = true;break;default:break;}}}

4.3.3 绘制菜单

menus.cpp 中定义绘制各级菜单的函数;对应的函数声明放在 common.h里。

代码如下:

//菜单函数
#include "common.h"//主菜单
void menus_main() {system("cls");		//清屏cout << "-----------------------------------------------------------" << endl;cout << "|                                                         |" << endl;cout << "|***************     1 添加联系人     ********************|" << endl;cout << "|***************     2 显示联系人     ********************|" << endl;cout << "|***************     3 修改联系人     ********************|" << endl;cout << "|***************     4 退      出     ********************|" << endl;cout << "|_________________________________________________________|" << endl;cout << "\n请选择(1 - 4):";
}
//添加联系人菜单
void menus_app() {cout << "-----------------------------------------------------------" << endl;cout << "|                                                         |" << endl;cout << "|*************** 请选择添加联系人类别 ********************|" << endl;cout << "|***************   1  办        公    ********************|" << endl;cout << "|***************   2  个        人    ********************|" << endl;cout << "|***************   3  退        出    ********************|" << endl;cout << "|_________________________________________________________|" << endl;cout << "\n请选择(1 - 3):";cin.get();
}
//显示联系人菜单
void menus_show() {cout << "-----------------------------------------------------------" << endl;cout << "|                                                         |" << endl;cout << "|*************** 请选择显示联系人类别 ********************|" << endl;cout << "|***************   1  全        部    ********************|" << endl;cout << "|***************   2  办        公    ********************|" << endl;cout << "|***************   3  个        人    ********************|" << endl;cout << "|***************   4  退        出    ********************|" << endl;cout << "|_________________________________________________________|" << endl;cout << "\n请选择(1 - 4):";
}
//修改联系人菜单
void menus_revise() {cout << "-----------------------------------------------------------" << endl;cout << "|                                                         |" << endl;cout << "|*************** 请选择修改联系人类别 ********************|" << endl;cout << "|***************   1  办        公    ********************|" << endl;cout << "|***************   2  个        人    ********************|" << endl;cout << "|***************   3  退        出    ********************|" << endl;cout << "|_________________________________________________________|" << endl;cout << "\n请选择(1 - 3):";
}
//删除联系人菜单
void menus_delete() {cout << "-----------------------------------------------------------" << endl;cout << "|                                                         |" << endl;cout << "|*************** 请选择删除联系人类别 ********************|" << endl;cout << "|***************   1  办        公    ********************|" << endl;cout << "|***************   2  个        人    ********************|" << endl;cout << "|***************   3  退        出    ********************|" << endl;cout << "|_________________________________________________________|" << endl;cout << "\n请选择(1 - 3):";
}

4.3.4 读取键盘输入

        在 read_input.cpp 中定义读取键盘输入的函数,包括读取菜单选择、读取输入的金额数、读取确认退出信息;这些函数都需要对输入做合法性校验,并返回正确的值。

代码如下:

//读取输入函数
#include "common.h"//读取键盘输入的菜单选项,进行合法性校验
char readMenuSelection(int options) {string str;while (true){getline(cin, str);//进行合法化校验if (str.size() != 1 || str[0] - '0' <= 0 || str[0] - '0' > options)cout << "输入错误,请重新选择:";elsebreak;}//输入合法return str[0];}//读取确认退出信息,并进行合法性校验
char readquitconfirm() {string str;while (true){getline(cin, str);//进行合法性校验if (str.size() != 1 || toupper(str[0]) != 'Y' && toupper(str[0]) != 'N')cout << "输入错误,请重新选择:";elsebreak;}//输入合法return toupper(str[0]);
}

4.3.5 实现具体操作功能

     在 operations.cpp 中,定义从文件加载数据、添加、显示、修改等操作对应的函数。

  1. (1)从文件加载数据

loadDataFromFile():逐行读取文件中数据,按空格将每个词赋值给Person中的每个成员,得到一个Person对象,并把它保存到数组中。

由于数组长度是固定的,这里应该用可变长的容器对象vector<Person>来保存;为了能够在函数中修改vector,应该把它的引用作为函数参数传入。

  1. (2)添加功能

        首先需要读取键盘输入的金额和备注信息;然后将其保存在一个AccountItem 对象中,并添加到数组,同时写入文件。

person_add():添加联系人主体函数

person_addOffice():记录办公类联系人,将数据添加到vector中,并调用insertIntoFile()函数,写入文件做持久化保存

person_addmyself():记录个人类联系人,将数据添加到vector中,并调用insertIntoFile()函数,写入文件做持久化保存

insertIntoFile():将一条账目写入文件中。

  1. (3)显示功能

        需要用for循环遍历整个数组,通过条件 筛选需要的联系人打印输出,并统计总和。

person_show():查询主体函数

showPerson():显示通讯录联系人

  1. (4)修改功能

        需要用for循环遍历整个数组,通过条件 筛选需要的联系人进行更改,更改后使用for循环再次遍历整个数组,重新写入文件中做持久化保存。

person_revise():修改联系人主体函数

change():遍历数组找到联系人进行更改,将更改后的结果重新写入文件

具体代码如下:

//涉及通讯录操作的函数
#include "common.h"
#include "person_item.h"//读取文件中的账目数据
void loadDataFromFile(vector<Person>& ps) {ifstream input(FILENAME);//逐行读取每一条数据,包装成Person对象Person p;string line;while (input >> p.PersonItem >> p.name >> p.iphone >> p.address) {ps.push_back(p);}input.close();
}//----------------------------------------添加-----------------------------------------------
//添加操作
void person_add(vector<Person>& ps) {//读取键盘选择,并做合法化校验char key = readMenuSelection(3);switch (key){case '1':			//办公person_addOffice(ps);break;case '2':			//个人person_addmyself(ps);break;case '3':			//返回主菜单break;default:break;}
}//记录办公类别通讯录
void person_addOffice(vector<Person>& ps) {//新构建一个Person对象Person p;//类型已经确定,就是办公p.PersonItem = OFFICE;//与用户交互,键盘输入姓名,电话,住址cout << "\n请输入姓名:";getline(cin, p.name);cout << "\n请输入电话:";getline(cin, p.iphone);cout << "\n请输入住址:";getline(cin, p.address);//添加到vector中ps.push_back(p);//写入文件做持久化保存insertIntoFile(p);//显示成功信息cout << "\n----------------添加成功----------------\n";cout << "\n请按回车键返回主菜单......." << endl;string str;getline(cin, str);}	//记录个人类别通讯录
void person_addmyself(vector<Person>& ps) {//新构建一个Person对象Person p;//类型已经确定,就是办公p.PersonItem = MYSELF;//与用户交互,键盘输入姓名,电话,住址cout << "\n请输入姓名:";getline(cin, p.name);cout << "\n请输入电话:";getline(cin, p.iphone);cout << "\n请输入住址:";getline(cin, p.address);//添加到vector中ps.push_back(p);//写入文件做持久化保存insertIntoFile(p);//显示成功信息cout << "\n----------------添加成功----------------\n";cout << "\n请按回车键返回主菜单......." << endl;string str;getline(cin, str);
}//将一条数据写入文件中
void insertIntoFile(const Person& p) {//创建一个ofstream对象,第二个参数表示以追加的方式进行写入ofstream output(FILENAME, ios::out | ios::app);output << p.PersonItem << "\t" << p.name << "\t" << p.iphone << "\t" << p.address << endl;output.close();
}//-------------------------------------显示----------------------------------------------------------------
void person_show(vector<Person>& ps) {//读取键盘选择,并做合法性校验char key = readMenuSelection(4);switch (key){case '1':					//所有showPerson(ps);break;case '2':					//办公showPerson(ps,OFFICE);break;case '3':					//个人showPerson(ps,MYSELF);break;case '4':					//返回主菜单break;default:break;}
}//显示所有通讯录
void showPerson(const vector<Person>& ps) {cout << "----------------------查询结果-----------------------" << endl;cout << "\n类型\t\t姓名\t\t电话\t\t住址\n" << endl;//遍历所有通讯录,并添加数目int count = 0;for (auto p : ps) {printPerson(p);++count;}//输出信息cout << "===========================================================" << endl;cout << "总联系人数:" << count << endl;cout << "\n请按回车键返回主菜单......" << endl;string str;getline(cin, str);
}//函数重载,显示联系人
void showPerson(const vector<Person>& ps,const string PersonItem) {cout << "----------------------查询结果-----------------------" << endl;cout << "\n类型\t\t姓名\t\t电话\t\t\t住址\n" << endl;//遍历所有通讯录,并添加数目int count = 0;for (auto p : ps) {if (p.PersonItem != PersonItem)continue;printPerson(p);++count;}//输出信息cout << "===========================================================" << endl;cout << "总联系人数:" << count << endl;cout << "\n请按回车键返回主菜单......" << endl;string str;getline(cin, str);
}//打印每一条通讯录数据
void printPerson(const Person& p) {cout << p.PersonItem << "\t\t" << p.name << "\t\t" << p.iphone << "\t\t" << p.address << endl;
}//----------------------------------------修改---------------------------------------------------------------------------
//修改联系人主体函数
void person_revise(vector<Person>& ps) {//读取键盘选择,并做合法化校验char key = readMenuSelection(3);switch (key){case '1':					//办公change(ps,OFFICE);break;case '2':					//个人change(ps,MYSELF);break;case '3':					//退出break;					default:break;}
}//修改联系人操作函数
void change(vector<Person>& ps, string item) {cout << "请输入您要修改的联系人姓名:";string name;bool found = false;while (!found) {getline(cin, name);for (auto& p : ps) {if (p.PersonItem == item && p.name == name) {string changeNmae;string changeIphone;string changeAddress;cout << "请输入更改后的姓名:";getline(cin, changeNmae);p.name = changeNmae;cout << endl;cout << "请输入更改后的电话:";getline(cin, changeIphone);p.iphone = changeIphone;cout << endl;cout << "请输入更改后的住址:";getline(cin, changeAddress);p.address = changeAddress;cout << endl;found = true;break;}}if (!found) {cout << "未找到此联系人,请重新输入:" << endl;}}// 将更改写回到文件,	trunc模式会将文件中的数据清空,然后重新写入新的内容ofstream outputFile(FILENAME, ios::out | ios::trunc);if (outputFile.is_open()) {for (const auto& p : ps) {outputFile << p.PersonItem << "\t" << p.name << "\t" << p.iphone << "\t" << p.address << endl;}outputFile.close();}else {cerr << "无法打开文件进行写入." << endl;}// 显示成功信息cout << "----------------修改成功----------------" << endl;cout << "请按回车键返回主菜单......." << endl;string str;getline(cin, str);
}

至此,我们就完成了对通讯录管理的设计与实现啦,你也快去试一下吧~

相关文章:

【C++】C++应用案例-通讯录管理系统

目录 一、整体介绍 1.1、需求和目标 1.2、整体功能描述 二、页面及功能描述 2.1 主菜单 2.2 添加联系人菜单 2.3 显示联系人菜单 2.4 修改联系人菜单 2.5 退出功能 三、流程设计 3.1 主流程 3.2 添加操作流程 3.3 显示联系人操作流程 3.4 修改联系人操作流程 四…...

使用Python自动批量提取增值税发票信息并导出为Excel文件

要批量提取增值税发票的关键信息并将其导出为 Excel 文件&#xff0c;可以使用 Python 脚本结合 pdfplumber&#xff08;用于解析 PDF 内容&#xff09;、pandas&#xff08;用于处理数据并导出 Excel&#xff09;等库来实现。以下是实现这一目标的详细步骤。 1. 环境设置 首…...

vitis (eclipse) 的Indexer不能搜索、不能跳转到函数和变量定义和声明不能打开调用层次的解决方法

在使用vitis(2021.1) 过程中&#xff0c;有一个非常方便实用的功能&#xff0c;就是在函数或变量等源代码上通过右键菜单或快捷键F3、F4、CtrlAltH&#xff0c;也可以按住Ctrl键然后鼠标停留在函数名或变量名上&#xff0c;点击出现的链接&#xff0c;可以跳转到函数或变量的定…...

最佳HR软件指南:11款高效管理工具

文章介绍了11款人力资源管理工具&#xff1a;Moka、友人才、北森HRSaaS、同鑫eHR、i人事、红海eHR、BambooHR、Skuad、Hibob、OrangeHRM、Verint。 在选择人力资源管理软件时&#xff0c;选错不仅浪费时间和金钱&#xff0c;还会影响团队的工作效率和员工满意度。本文总结了11款…...

家长为孩子出国留学择校的四个步骤

如何为孩子选择最好的学校&#xff1f;无论您是选择公立或私立学校还是在家上学&#xff0c;无论您是否支付学费&#xff0c;都必须仔细规划。在为孩子选择学校的过程中&#xff0c;以下部分有供您考虑的问题。 写下对你来说最重要的五件事 在考虑选择学校时&#xff0c;您可…...

数据挖掘可以挖掘什么类型的模式?

一、挖掘频繁模式、关联和相关性 频繁模式&#xff08;frequent pettern&#xff09;是在数据中频繁出现的模式。 频繁项集一般是指频繁的在事务数据集中一起出现的商品的集合。 频繁出现的子序列&#xff0c;如顾客倾向于先买相机&#xff0c;再买内存卡这样的模式就是一个…...

JAVA中的隐式参数this

在Java中&#xff0c;this 关键字是一个非常重要的隐式参数&#xff0c;它代表当前对象的引用。通过 this&#xff0c;你可以访问类中的字段&#xff08;属性&#xff09;、方法以及构造函数中的参数&#xff08;当参数名与字段名相同时&#xff0c;用于区分&#xff09;。虽然…...

ThreadLocal 使用和详解避坑

在多线程编程中&#xff0c;每个线程都有自己的线程栈和线程本地存储。线程栈用于存储方法调用的信息&#xff0c;而线程本地存储则是每个线程私有的存储空间&#xff0c;用于存储线程的局部变量。ThreadLocal类提供了一种简单的方式来实现线程本地存储&#xff0c;它允许将线程…...

Python中使用类方法的返回值在其他方法中继续调用,return self进行链式调用

文章目录 return self进行链式调用继续思考&#xff0c;以下内容可以不看如果self中没有初始化valueself中定义其他变量&#xff0c;调用类方法外的函数 return self进行链式调用 在Python中&#xff0c;可以使用类方法的返回值在其他方法中继续调用。这通常通过返回类实例&am…...

基于IOT架构的数据采集监控平台!

LP-SCADA数据采集监控平台是蓝鹏测控推出的一款聚焦于工业领域的自动化数据采集监控系统&#xff0c; 助力数字工厂建设的统一监控平台。 为企业提供从下到上的完整的生产信息采集与集成服务&#xff0c;从而为企业综合自动化、工厂数字化及完整的"管控一体化”的解决方案…...

初见scikit-learn之基础教程

初见scikit-learn之基础教程 scikit-learn 基础教程 1. scikit-learn 简介1.1 什么是 scikit-learn&#xff1f;1.2 scikit-learn 的主要功能 2. 安装 scikit-learn2.1 安装方法2.2 验证安装 3. scikit-learn 基本使用3.1 数据加载与预处理3.1.1 加载数据集3.1.2 数据拆分3.1.3…...

基于STM32的嵌入式深度学习系统教程

目录 引言环境准备嵌入式深度学习系统基础代码实现&#xff1a;实现嵌入式深度学习系统 数据采集与预处理深度学习模型训练与优化模型部署与推理实时数据处理与反馈应用场景&#xff1a;智能物联网设备常见问题与解决方案收尾与总结 引言 随着深度学习在各种应用中的广泛采用…...

hive udf去掉map中的一个或者多个key

实现一个hive udf,可以将Map中的某一个或者多个key去掉,这里要继承GenericUDF 这个抽象类,然后Override evaluate这个函数即可,可以把执行这个udf前初始化的一些内容放在initialize方法内,比如参数的判断,函数的返回值类型等等。 代码写好之后,可以用如下方法创建这个函…...

模型量化技术综述:揭示大型语言模型压缩的前沿技术

大型语言模型&#xff08;LLMs&#xff09;通常因为体积过大而无法在消费级硬件上运行。这些模型可能包含数十亿个参数&#xff0c;通常需要配备大量显存的GPU来加速推理过程。 因此越来越多的研究致力于通过改进训练、使用适配器等方法来缩小这些模型的体积。在这一领域中&am…...

一文掌握Prompt:万能框架+优化技巧+常用指标

&#x1f449;目录 1 写在前面 2 Prompt 万能框架 3 框架的细化 4 在框架上增加更多信息&#xff08;RAG&#xff09; 5 让大模型更好的思考&#xff08;CoT&#xff09; 6 附加技巧 7 优化方式及常用指标 8 写在最后 随着大模型在2023年横空出世&#xff0c;“Prompt 工程” 应…...

Vue 常用组件间通信方式

Vue 常用组件间通信方式 1. 父子组件通信 1.1 Props 父组件通过 props 向子组件传递数据&#xff0c;子组件通过 props 接收数据。 <!-- ParentComponent.vue --> <template><ChildComponent :message"parentMessage"></ChildComponent>…...

NineData云原生智能数据管理平台新功能发布|2024年7月版

本月发布 12 项更新&#xff0c;其中性能优化 3 项、功能优化 8 项、安全性发布 1 项。 1. 性能优化 数据复制 - SQL Server 增量性能优化 调整读取和写入方式&#xff0c;让 SQL Server 增量复制的性能轻松达到 5000 RPS 以上。 数据复制 - Doris|SelectDB|StarRocks 性能优…...

验收测试:确保软件符合业务需求和合同要求

目录 前言1. 验收测试的概念1.1 用户验收测试&#xff08;UAT&#xff09;1.2 操作验收测试&#xff08;OAT&#xff09; 2. 验收测试的主要作用2.1 确认业务需求的满足2.2 验证合同要求的实现2.3 提升用户信心 3. 验收测试在整个测试中的地位3.1 测试的最后一道关卡3.2 用户与…...

Qt | QChartView+QDateTimeAxis(日期和时间数据图表)+QPieSeries(饼图)

点击上方"蓝字"关注我们 01、QDateTimeAxis QDateTimeAxis 是 Qt 中用于图表的轴类,它专门用于处理日期和时间数据。这个类允许你在图表上显示和解释与日期和时间相关的数据点。例如,在 Qt 的图表库中,你可以使用 QDateTimeAxis 来创建一个时间序列图表,展示股票…...

用闲置的阿里云服务器使用 NPS 实现内网穿透

最近有个项目需要给外地的同事预览一下&#xff0c;但是公司没有可以公网访问的测试服务器&#xff0c;所以想到用内网穿透的方式让外地同事可以访问到我的本机。刚好我有一台阿里云的服务器&#xff0c;双十一打折买了3年&#xff0c;1000左右&#xff0c;2核8G&#xff0c;买…...

滴滴盖亚计划ETA数据集实战:如何用Python处理智能交通数据(附完整代码)

滴滴盖亚ETA数据集实战&#xff1a;Python智能交通数据处理全流程解析 引言&#xff1a;智能交通时代的ETA技术价值 在早高峰的深圳深南大道上&#xff0c;网约车司机王师傅刚接单就面临抉择&#xff1a;系统推荐的三条路线中&#xff0c;哪一条能最快到达乘客上车点&#xf…...

探索RBMO - BiLSTM - Attention分类算法:MATLAB实现与应用

【24年5月顶刊算法】RBMO-BiLSTM-Attention分类 基于红嘴蓝鹊优化器(RBMO)-双向长短期记忆网络(BiLSTM)-注意力机制(Attention)的数据分类预测(可更换为回归/单变量/多变量时序预测&#xff0c;前私)&#xff0c;Matlab代码&#xff0c;可直接运行&#xff0c;适合小白新手 无需…...

Python项目依赖管理:pipreqs vs pip freeze,哪个更适合你的项目?

Python项目依赖管理&#xff1a;pipreqs vs pip freeze&#xff0c;哪个更适合你的项目&#xff1f; 在Python开发中&#xff0c;依赖管理是项目维护的重要环节。一个清晰、准确的依赖清单不仅能确保项目在不同环境中稳定运行&#xff0c;还能简化团队协作和部署流程。面对pip…...

从MATLAB算法到MiniCPM-V-2_6模型:科学计算与AI的融合实践

从MATLAB算法到MiniCPM-V-2_6模型&#xff1a;科学计算与AI的融合实践 如果你经常和MATLAB打交道&#xff0c;可能会遇到这样的场景&#xff1a;跑完一个复杂的仿真&#xff0c;生成了几十张图表和一堆数据&#xff0c;然后需要花上半天时间&#xff0c;手动整理结果、撰写分析…...

告别插件冲突!手把手教你手动安装Obsidian动态目录插件(Dynamic Table of Contents)

告别插件冲突&#xff01;Obsidian动态目录插件手动安装全指南 为什么需要手动安装动态目录插件&#xff1f; Obsidian作为一款强大的知识管理工具&#xff0c;其插件生态让用户能够高度自定义工作流。然而&#xff0c;插件间的兼容性问题常常成为用户痛点。许多用户习惯使用Fl…...

CLIP-GmP-ViT-L-14匹配精度实测:Softmax置信度排序效果惊艳案例集

CLIP-GmP-ViT-L-14匹配精度实测&#xff1a;Softmax置信度排序效果惊艳案例集 1. 引言&#xff1a;当图片遇见文字&#xff0c;CLIP如何精准“读懂”&#xff1f; 想象一下&#xff0c;你有一张照片&#xff0c;里面可能是一只猫、一辆车&#xff0c;或者一片风景。如果让你用…...

高效判断点在多边形内的算法:Winding Number与Crossing Number的对比与实践

1. 为什么需要判断点在多边形内&#xff1f; 判断一个点是否位于多边形内部是计算几何中的经典问题&#xff0c;这个看似简单的需求在实际开发中随处可见。比如地图应用中判断用户位置是否在某个行政区域内&#xff0c;游戏开发中检测子弹是否击中目标&#xff0c;CAD软件中确定…...

基于Python的宽带业务管理系统毕设源码

博主介绍&#xff1a;✌ 专注于Java,python,✌关注✌私信我✌具体的问题&#xff0c;我会尽力帮助你。一、研究目的本研究旨在设计并实现一个基于Python的宽带业务管理系统&#xff0c;以提升宽带服务提供商的业务管理效率和客户服务质量。具体研究目的如下&#xff1a;系统架构…...

10分钟搭建FunASR智能语音点餐系统:餐饮服务革命性升级指南

10分钟搭建FunASR智能语音点餐系统&#xff1a;餐饮服务革命性升级指南 FunASR是一个开源的端到端语音识别工具包&#xff0c;提供了SOTA预训练模型&#xff0c;能够帮助开发者快速构建语音交互应用。本文将详细介绍如何在10分钟内利用FunASR搭建智能语音点餐系统&#xff0c;…...

OpenClaw极简部署:5分钟体验Qwen3.5-9B基础自动化功能

OpenClaw极简部署&#xff1a;5分钟体验Qwen3.5-9B基础自动化功能 1. 为什么选择这个组合&#xff1f; 第一次听说OpenClaw时&#xff0c;我正被日常重复性工作困扰——每天要手动整理会议纪要、归档文件、检查数据报表。作为一个技术背景的产品经理&#xff0c;我既想要自动…...