C++笔记打卡第14天(文件管理、职工操作系统)

server/2024/9/20 6:00:52/ 标签: c++, 笔记

1.文本文件(写文件)

文件类型分为两种:

  • 文本文件:文件以文本的ASCII码形式存储在计算机中
  • 二进制文件:文件以文本的二进制形式存储在计算机中,用户一般不能直接读懂它

操作文件的三大类

  • ofstream:写操作
  • ifstream:读操作
  • fstream:读写操作

写文件:

  • 包含头文件 #include <fstream>
  • 创建流对象 ofstream ofs;
  • 打开文件 ofs.open(”文件路径”,打开方式);
  • 写数据 ofs<<”写入的数据”;
  • 关闭文件 ofs.close();
文件打开方式解释
ios::in为读文件而打开文件
ios::out为写文件而打开文件
ios::ate初始位置:文件尾
ios::app追加方式写文件
ios::trunc如果文件存在先删除,再创建
ios::binary二进制方式

文件打开方式可以配合使用,利用 | 操作符。如用二进制方式写文件 ios::binary | ios::out

void test01()
{// 1.文件操作必须包含头文件fsream// 2.创建流对象ofstream ofs;// 3.制定打开方式ofs.open("test.txt", ios::out);// 4.写<<内容ofs << "张三" << endl;ofs << "男" << endl;ofs << "18" << endl;// 5.关闭文件ofs.close();
}

2.文本文件(读文件)

读文件:

  • 包含头文件 #include <fstream>
  • 创建流对象 ifstream ifs;
  • 打开文件并判断文件是否打卡成功 ifs.open(”文件路径”,打开方式);
  • 读数据
  • 关闭文件 ifs.close();
void test01()
{// 1.创建流对象ifstream ifs;// 2.制定打开方式ifs.open("test.txt", ios::in);if (!ifs.is_open())  // 判断文件是否打开成功{cout << "文件打开失败" << endl;return;}// 3.读数据char buf[1024] = {0};while(ifs >> buf){cout << buf << endl;}// 一行一行读char buf[1024] = {0};while(ifs.getline(buf, sizeof(buf))){cout << buf << endl;}// 一行一行读string buf;while(getline(ifs, buf)){cout << buf << endl;}// 一个一个读char c;while((c = ifs.get()) != EOF){//cout << c;//}// 4.关闭文件ifs.close();
}

3.二进制文件(写文件)

  • 二进制方式写文件主要利用流对象调用成员write
  • 函数原型:ostream& write(const char* buffer,int len);
class Person
{
public:char m_Name[64];int m_Age;
};
void test01()
{// 1.包含头文件// 2.创建流对象ofstream ofs;// 3.打开文件ofs.open("person.txt", ios::out | ios::binary);// 4.写文件Person p = {"张三", 18};ofs.write((const char *)&p, sizeof(Person));// 5.关闭文件ofs.close();
}

4.二进制文件(写文件)

  • 二进制方式读文件主要利用流对象调用成员函数read
  • 函数原型:istream& read(char *buffer, int len);
class Person
{
public:char m_Name[64];int m_Age;
};
void test01()
{// 1.包含头文件// 2.创建流对象ifstream ifs;// 3.打开文件 判断文件是否打开成功ifs.open("person.txt", ios::in | ios::binary);if(!ifs.is_open()){cout << "文件打开失败" << endl;}// 4.写文件Person p;ifs.read((char *)&p, sizeof(Person));cout << p.m_Name << p.m_Age << endl;// 5.关闭文件ifs.close();
}

5.职工管理系统

公司中职工分为三类:普通员工、经理、老板,显示信息时,需要显示职工编号、职工姓名、职工岗位、以及职责

  • 普通员工职责:完成经理交给的任务
  • 经理职责:完成老板交给的任务,并下发任务给员工
  • 老板职责:管理公司所有事务

管理系统重需要实现的功能如下:

  • 退出管理程序:退出当前管理系统
  • 增加职工信息:实现批量添加职工功能,将信息录入到文件中,职工信息为:职工编号、姓名、部门编号
  • 显示职工信息:显示公司内部所有职工的信息
  • 删除离职职工:按照编号删除指定的职工
  • 修改职工信息:按照编号修改职工个人信息
  • 查找职工信息:按照职工的编号或者职工的姓名进行查找相关的人员信息
  • 按照编号排序:按照职工编号,进行排序,排序规则由用户指定
  • 清空所有文档:清空文件中记录的所有职工信息(清空前需要再次确认,防止误删)

第一步:实例化管理者对象

创建总执行文件 main.cpp,workerManager.h 和 workerManager.cpp 三个文件。

int main()
{// 实例化管理者对象WorkerManager wm;system("pause");return 0;
}

在workerManager.h中设置每一个用到的函数声明:

#pragma once
#include <iostream>class WorkerManager
{
public:WorkerManager(); ~WorkerManager(); 
};

 在workerManager.cpp 里写每一个函数的具体实现:

#include <workerManager.h>// 构造函数
WorkerManager::WorkerManager()
{}// 析构函数
WorkerManager::~WorkerManager()
{}

第二步:创建抽象的员工类别,以及三个派生类(普通员工、经理、老板)

创建 worker.h,设置抽象的员工类别作为基类

#pragma once
#include <iostream>
#include <string>
using namespace std;class Worker
{
public:// 显示个人信息virtual void showInfor() = 0;// 获取岗位名称virtual string showDepartment() = 0;int m_id;string m_name;int m_deptid;
};

在基类基础上创建三种子类,表示三种员工(普通员工、经理、老板)

普通员工 employee.h 每个函数的声明:

#pragma once
#include <iostream>
#include <string>
#include <worker.h>
using namespace std;class Employee:public Worker
{
public:Employee(int id, string name, int deptid);virtual void showInfor();virtual string showDepartment();
};

普通员工 employee.cpp 每个函数的具体实现:

#include <employee.h>Employee::Employee(int id, string name, int deptid)
{m_name = name;m_id = id;m_deptid = deptid;
}
void Employee::showInfor()
{cout << "职工编号: " << this->m_id;cout << "\t职工姓名: " << this->m_name;cout << "\t岗位: " << this->showDepartment();cout << "\t岗位职责: 完成经理交代的任务" << endl;
}
string Employee::showDepartment()
{return string("员工");
}

之后再以同样的方式创建Manage.h , Mangae.cpp, Boss.h, Boss.cpp。

第三步:显示菜单

在workerManager.h中加入:

// 展示菜单
void show_Menu();

在workerManager.cpp中加入:

void WorkerManager::show_Menu()
{cout << "*********************************" << endl;cout << "*******欢迎使用职工管理系统******" << endl;cout << "********0.退出管理程序***********" << endl;cout << "********1.增加职工信息***********" << endl;cout << "********2.显示职工信息***********" << endl;cout << "********3.删除高职职工***********" << endl;cout << "********4.修改职工信息***********" << endl;cout << "********5.查找职工信息***********" << endl;cout << "********6.按照编号排序***********" << endl;cout << "********7.清空所有文档***********" << endl;cout << "*********************************" << endl;cout << endl;
}

第四步:选择为0时退出系统

在workerManager.h中加入声明:

// 退出
void ExitSystem();

在workerManager.cpp中加入具体实现:

void WorkerManager::ExitSystem()
{cout << "欢迎下次使用" << endl;system("pause");exit(0);
}

第五步:选择为1时添加职工

用户在批量创建时,可能会创建不同种类的职工。如果想将所有不同种类的员工都收入到一个数组中,可以将所有员工的指针维护到一个数组里。如果想在程序中维护这个不定长度的数组,可以将数组创建到堆区,并利用Worker **的指针维护。

在workerManager.h中加入声明:

// 记录职工人数
int m_EmpNum;
// 记录职工数组的指针
Worker **m_EmpArray;
void Add_Emp();

在workerManager.cpp中加入具体实现:

void WorkerManager::Add_Emp()
{cout << "请输入需要添加的职工的数量:" << endl;int addNum = 0;cin >> addNum;if(addNum > 0){int newSize = this->m_EmpNum + addNum; // 新空间人数 = 已经记录的人数 + 新增人数// 开辟存放指针的新空间Worker** newSpace = new Worker*[newSize];// 将已经记录的内容放入新的空间if(this->m_EmpArray != NULL){for(int i=0; i < this->m_EmpNum; i++){newSpace[i] = this->m_EmpArray[i];}}// 添加新数据for(int i=0; i<addNum; i++){int id;string name;int deptid;cout << "请输入第" << i+1 << "位职工的编号:" << endl;cin >> id;cout << "请输入第" << i+1 << "位职工的姓名:" << endl;cin >> name;cout << "请选择第" << i+1 << "位职工的岗位(1-普通员工, 2-经理, 3-老板):" << endl;cin >> deptid;Worker *worker = NULL;switch(deptid){case 1:worker = new Employee(id, name, 1);break;case 2:worker = new Manager(id, name, 2);break;case 3:worker = new Boss(id, name, 3);break;default:break;}// !将新创建的职工指针,保存到数组中newSpace[this->m_EmpNum+i] = worker;}// 释放原有空间delete[] this->m_EmpArray;// 更新this->m_EmpArray = newSpace;this->m_EmpNum = newSize;// 更新职工不为空的标志this->is_Empty = false;// 保存数据到文件中this->save();cout << "成功添加" << addNum << "位员工!" << endl;}else{cout << "输入有误" << endl;}system("pause");system("cls");
}

第六步:将信息保存到文本文件中

在workerManager.h中加入声明:

void save();

在workerManager.cpp中加入具体实现:

void WorkerManager::save()
{ofstream ofs;ofs.open(FILENAME, ios::out);for(int i=0; i<this->m_EmpNum; i++){ofs << this->m_EmpArray[i]->m_id << " "<< this->m_EmpArray[i]->m_name << " "<< this->m_EmpArray[i]->m_deptid << endl;}ofs.close();
}

第七步:选择为2时显示职工

在workerManager.h中加入声明:

    // 判断文件是否为空(之前是否已经有存入的数据)bool is_Empty;// 如果有,统计文件中的人数int get_EmpNum();// 初始化m_EmpArray数组void init_Emp();// 显示职工void show_Emp();

在workerManager.cpp中加入具体实现:(在构造函数中加入三种初始情况,没有初始文件时,有出示文件但没有数据时,有文件且有数据时)对于前两种情况,在构造函数㕜将this->m_EmpNum设为0,this->m_EmpArray设为空。

WorkerManager::WorkerManager()
{// 文件不存在时ifstream ifs;ifs.open(FILENAME, ios::in);if(!ifs.is_open()){cout << "初始员工文件不存在" << endl;// 初始化属性this->m_EmpNum = 0;this->m_EmpArray = NULL;this->is_Empty = true; ifs.close(); return;}// 文件存在且数据为空char ch;ifs >> ch;if(ifs.eof()){// 代表文件为空cout << "初始员工文件为空" << endl;// 初始化属性this->m_EmpNum = 0;this->m_EmpArray = NULL;this->is_Empty = true; ifs.close(); return;}// 文件存在且有数据this->is_Empty = false;int num = this->get_EmpNum();cout << "已存储" << num << "位职工信息" << endl;this->m_EmpNum = num;this->m_EmpArray = new Worker*[num];this->init_Emp();}

对于第三种情况,有文件且有数据,首先求得文件中数据的长度,再将数据初始化到m_EmpArray中:

int WorkerManager::get_EmpNum()
{ifstream ifs;ifs.open(FILENAME, ios::in);int num = 0;int id;string name;int deptid;while(ifs >> id && ifs >> name && ifs >> deptid){num++;}return num;
}void WorkerManager::init_Emp()
{ifstream ifs;ifs.open(FILENAME, ios::in);int id;string name;int deptid;int index = 0;while(ifs >> id && ifs >> name && ifs >> deptid){Worker *worker = NULL;if (deptid == 1){worker = new Employee(id, name, deptid);}else if (deptid == 2){worker = new Manager(id, name, deptid);}else if (deptid == 3){worker = new Boss(id, name, deptid);}this->m_EmpArray[index] = worker;index++;}ifs.close();
}

 显示所有职工信息:

void WorkerManager::show_Emp()
{if(this->is_Empty){cout << "文件不存在或记录为空" << endl;}else{for(int i=0; i<this->m_EmpNum; i++){this->m_EmpArray[i]->showInfor();}}system("pause");system("cls");
}

第八步:选择为3时删除职工

在workerManager.h中加入声明:

    void delete_Emp();int is_exist(int id);

先判断该职工是否存在,存在则返回下标,不存在返回-1:

// 判断职工是否存在,不存在返回-1
int WorkerManager::is_exist(int id)
{int index = -1;for (int i=0; i<this->m_EmpNum; i++){if(this->m_EmpArray[i]->m_id == id){index = i;break;}}return index;
}

再删除该职工信息:

void WorkerManager::delete_Emp()
{if(this->is_Empty){cout << "文件不存在或记录为空" << endl;}else{cout << "请输入需要删除的职工的ID:" << endl;int id;cin >> id;int index = this->is_exist(id);if(index != -1){for(int i=index; i<this->m_EmpNum-1; i++){this->m_EmpArray[i] = this->m_EmpArray[i+1];}this->m_EmpNum--;// 将文件中数据同步更新this->save();cout << "删除成功" << endl;}else{cout << "删除失败,该职工不存在" << endl;}}system("pause");system("cls");
}

第九步:选择为4时修改信息

在workerManager.h中加入声明:

void change_Emp();

在workerManager.cpp中加入具体实现,先判断传入的这个人的id是否存在,再根据新建数据的格式修改信息:

void  WorkerManager::change_Emp()
{if(this->is_Empty){cout << "文件不存在或记录为空" << endl;}else{cout << "请输入需要修改信息的职工的ID:" << endl;int id;cin >> id;int index = this->is_exist(id);if(index != -1){cout << "查到系统中第" << index+1 << "号职工" << endl;delete this->m_EmpArray[index];int id;string name;int deptid;cout << "请输入新的职工编号:" << endl;cin >> id;cout << "请输入新的职工姓名:" << endl;cin >> name;cout << "请输入新的职位编号:" << endl;cin >> deptid;Worker *worker = NULL;switch(deptid){case 1:worker = new Employee(id, name, 1);break;case 2:worker = new Manager(id, name, 2);break;case 3:worker = new Boss(id, name, 3);break;default:break;}// !将创建的职工指针,保存到数组中this->m_EmpArray[index] = worker;cout << "修改成功" << endl;this->save(); }else{cout << "修改失败,该职工不存在" << endl;}}system("pause");system("cls");
}

第十步:选择为5时查找员工

在workerManager.h中加入声明:

    void Find_Emp();

在workerManager.cpp中加入具体实现(两种查找方式,第一种按编号查找,先判断此人是否存在,存在的返回数组指针的下标;第二种按姓名查找,遍历指针数组对应的m_name):

void WorkerManager::Find_Emp()
{if(this->is_Empty){cout << "文件不存在或记录为空" << endl;}else{cout << "请输入查找方式(1-按编号查找,2-按姓名查找):" << endl;int select = 0;cin >> select;if(select == 1){cout << "请输入需要查找的职工的ID:" << endl;int id;cin >> id;int index = this->is_exist(id);if(index != -1){cout << "查找成功,该职工信息如下:" << endl;this->m_EmpArray[index]->showInfor();}else{cout << "查找失败,该职工不存在" << endl;}}else if(select == 2){cout << "请输入需要查找的职工的姓名:" << endl;bool tag = false;string name;cin >> name;for(int i=0; i<this->m_EmpNum; i++){if(this->m_EmpArray[i]->m_name == name){tag = true;cout << "查找成功,该职工信息如下:" << endl;this->m_EmpArray[i]->showInfor();}}if(tag == false){cout << "查找失败,该职工不存在" << endl;}}else{cout << "输入错误" << endl;}}system("pause");system("cls");
}

第11步:选择为6时排序

在workerManager.h中加入声明:

    void sort_Emp();

在workerManager.cpp中加入具体实现,有两种排序方式,按照职工编号升序或降序。用双重循环找到最小的职工对应的m_id,同时按照升序/降序排列。外层循环是确定最大值/最小值所放的位置,内层循环是寻找未排序数组中的最小值

void WorkerManager::sort_Emp()
{if(this->is_Empty){cout << "文件不存在或记录为空" << endl;system("pause");system("cls");}else{cout << "请选择排序方式(1-按照职工编号升序排列,2-按照职工编号降序排列):" << endl;int select = 0;cin >> select;for(int i=0; i<this->m_EmpNum; i++){int minOrMax = i;for(int j=i+1; j<this->m_EmpNum; j++){if(select == 1) // 升序{if(this->m_EmpArray[minOrMax]->m_id > this->m_EmpArray[j]->m_id){minOrMax = j;}}else // 降序{if(this->m_EmpArray[minOrMax]->m_id < this->m_EmpArray[j]->m_id){minOrMax = j;}}}if(i != minOrMax){Worker *temp = this->m_EmpArray[i];this->m_EmpArray[i] = this->m_EmpArray[minOrMax];this->m_EmpArray[minOrMax] = temp;} }cout << "排序成果,排序后结果为:" << endl;this->save();this->show_Emp();}
}

第12步:选择为7时清除信息

在workerManager.h中加入声明:

    void deleteall();

在workerManager.cpp中加入具体实现,在删除之前先进行确认:

void WorkerManager::deleteall()
{cout << "确认清空? (1-yes,2-no)" << endl;int select = 0;cin >> select;if(select == 1){ofstream ofs;ofs.open(FILENAME, ios::trunc);  // 删除文件后重新创建ofs.close();// 删除堆区的每个职工对象和数组指针if(this->m_EmpArray != NULL){for(int i=0; i<this->m_EmpNum; i++){if(this->m_EmpArray[i] != NULL){delete this->m_EmpArray[i];}}delete[] this->m_EmpArray;this->m_EmpArray = NULL;this->m_EmpNum = 0;this->is_Empty = true;cout << "清空完毕" << endl;}}system("pause");system("cls");
}

根据这里的实现,进一步修改WorkerManager的析构函数:

WorkerManager::~WorkerManager()
{if(this->m_EmpArray != NULL){for(int i=0; i<this->m_EmpNum; i++){if(this->m_EmpArray[i] != NULL){delete this->m_EmpArray[i];}}delete[] this->m_EmpArray;this->m_EmpArray = NULL;}
}

最后:主函数设置分支结构

int main()
{// 实例化管理者对象WorkerManager wm;int choice = 0;while(true){wm.show_Menu();cout << "请输入您的选择:" << endl;cin >> choice;switch(choice){case 0: // 退出系统wm.ExitSystem();break;case 1:  // 增加职工wm.Add_Emp();break;case 2:  // 显示职工wm.show_Emp();break;case 3:  // 删除职工wm.delete_Emp();break;case 4:  // 修改职工wm.change_Emp();break;case 5: // 查找职工wm.Find_Emp();break;case 6:  // 排序职工wm.sort_Emp();break;case 7:  // 清空职工wm.deleteall();break;    default:system("cls"); // 清屏break;}}system("pause");return 0;
}

http://www.ppmy.cn/server/6751.html

相关文章

【嵌入式学习】ARM day04.17

一、主要逻辑 写入数据&#xff1a; 主机发送起始信号主机发送8bit从机地址1bit写标志&#xff08;0&#xff09;从机回应应答信号主机发送8bit从机的寄存器地址从机回应应答信号主机发送8bit数据从机回应应答主机发送8bit数据从机回应应答主机发起终止信号 读取数据&#x…

原生实现ajax

1 什么是ajax AJAX Asynchronous JavaScript and XML&#xff08;异步的 JavaScript 和 XML&#xff09;。 AJAX 不是新的编程语言&#xff0c;而是一种使用现有标准的新方法。 AJAX 最大的优点是在不重新加载整个页面的情况下&#xff0c;可以与服务器交换数据并更新部分网…

数码摄影色彩构成,数码相机色彩管理

一、资料描述 本套摄影色彩资料&#xff0c;大小58.54M&#xff0c;共有6个文件。 二、资料目录 《抽象彩色摄影集》.阿瑟.pdf 《色彩构成》.pdf 《色彩学》.星云.扫描版.pdf 《摄影色彩构成》.pdf 《数码相机色彩管理》.pdf 数码摄影进阶之4《色彩篇》.pdf 三、资料下…

大坝安全监测GNSS接收机:保障水库安全

大坝安全一直是社会关注的焦点之一。为了及时监测大坝的变形和位移情况&#xff0c;以预防可能发生的危险事故&#xff0c;GNSS接收机成为了不可或缺的仪器之一。本文将详细介绍GNSS接收机在大坝安全监测中的应用及其重要性。 一、GNSS接收机是什么 GNSS全球导航卫星系统&…

Gradle 进阶学习之 文件操作

1、本地文件 在 Gradle 中&#xff0c;Project.file(java.lang.Object) 方法是一个非常有用的工具&#xff0c;它允许你以一种类型安全的方式引用文件。这个方法可以接收一个字符串路径&#xff0c;返回一个 File 对象&#xff0c;这个对象代表的是一个相对于当前项目目录&…

生成对抗网络GAN的扩展应用理解

注&#xff1a;本文仅个人学习理解&#xff0c;如需详细内容请看原论文&#xff01; 一、cycleGAN 1.整体架构&#xff1a; 将图片A通过生成器生成图片B&#xff0c;然后通过判别器判别图片B的真假&#xff1b;并且图片B通过另一个生成器生成A‘&#xff0c;让A和A’近似。 2…

小红书电商运营实战课,从0打造全程实操(65节视频课)

课程内容&#xff1a; 1.小红书的电商介绍 .mp4 2.小红书的开店流程,mp4 3.小红书店铺基础设置介绍 ,mp4 4.小红书店铺产品上架流程 .mp4 5.客服的聊天过程和子账号建立 .mp4 6.店铺营销工具使用和后台活动参加 .mp4 7.小红书产品上架以及拍单教程,mp4 8.小红书如何选品…

自定义类似微信效果Preference

1. 为自定义Preference 添加背景&#xff1a;custom_preference_background.xml <?xml version"1.0" encoding"utf-8"?> <selector xmlns:android"http://schemas.android.com/apk/res/android"><item><shape android:s…

TCP/IP协议—HTTP

TCP/IP协议—HTTP HTTP协议HTTP通讯特点HTTP通讯流程 HTTP请求报文请求方法 HTTP应答报文状态码 HTTP协议 超文本传输协议&#xff08;Hypertext Transfer Protocol&#xff0c;HTTP&#xff09;是一种请求-响应的协议&#xff0c;用户可以通过HTTP向服务器上传、下载数据。HT…

04—常用方法和正则表达式

一、字符串 1.length 属性返回字符串的长度(字符数)。 2.在字符串中查找字符串 indexOf() 字符串使用 indexOf() 来定位字符串中某一个指定的字符首次出现的位置 如果没找到对应的字符函数返回-1 lastIndexOf() 方法在字符串末尾开始查找字符串出现的位置。 3.replace() 方…

C#创建磁性窗体的方法:创建特殊窗体

目录 一、磁性窗体 二、磁性窗体的实现方法 (1)无标题窗体的移动 (2)Left属性 (3)Top属性 二、设计一个磁性窗体的实例 &#xff08;1&#xff09;资源管理器Resources.Designer.cs设计 &#xff08;2&#xff09;公共类Frm_Play.cs &#xff08;3&#xff09;主窗体 …

使用WebSocket实现答题积分排名实时更新的功能

需求分析 接到一个需求&#xff0c;是一个答题积分小程序&#xff0c;其中有一个功能需求是需要实时更新答题积分排名的。之前通常比较常见的需求&#xff0c;都是指定某个时间点才更新答题排行榜的数据的。 经过技术调研&#xff0c;要实现答题积分排名实时更新的功能&#…

docker 安装geoipupdate

前提是docker已安装 一&#xff1a;执行命令&#xff1a; docker run --env-file /usr/local/etc/GeoIP.conf -v /usr/local/GeoIP2:/usr/share/GeoIP ghcr.io/maxmind/geoipupdate /usr/local/etc/GeoIP.conf &#xff1a;本地配置的账号&#xff0c;秘钥 GEOIPUPDATE_AC…

k8s安装记录

k8s安装记录 如无特别说明&#xff0c;则该步操作指在所有的机器上执行&#xff01;&#xff01;&#xff01; 如无特别说明&#xff0c;则该步操作指在所有的机器上执行&#xff01;&#xff01;&#xff01; 如无特别说明&#xff0c;则该步操作指在所有的机器上执行&#…

iOS知识点---Runloop

iOS 中的 Runloop 机制是一种事件驱动模型&#xff0c;用于管理和调度线程上的事件&#xff0c;确保线程在有工作要做时保持活跃&#xff0c;无事可做时进入休眠状态以节省系统资源。以下是 Runloop 机制的关键组成部分及其工作原理&#xff1a; 关键组成部分与原理&#xff1…

4 种策略让 MySQL 和 Redis 数据保持一致

先阐明一下 MySQL 和 Redis 的关系&#xff1a;MySQL 是数据库&#xff0c;用来持久化数据&#xff0c;一定程度上保证数据的可靠性&#xff1b;Redis 是用来当缓存&#xff0c;用来提升数据访问的性能。 关于如何保证 MySQL 和 Redis 中的数据一致&#xff08;即缓存一致性问…

过拟合与欠拟合

过拟合与欠拟合 过拟合有较为明显的对比可以判断&#xff0c;但欠拟合却是不容易判断的。 训练集效果很好&#xff0c;测试集效果变差&#xff0c;在保证训练集与测试集样本分布一致的情况下&#xff0c;很容易得出过拟合的结论。 欠拟合不太容易通过这种直接的对比来判断。 …

深入解读:BIO、NIO与IO多路复用——理解现代网络编程基石

在现代软件开发中&#xff0c;高效的数据交换是构建高性能网络应用的核心要素。深入理解输入输出&#xff08;Input/Output,简称IO&#xff09;模型的底层原理与工作机制&#xff0c;对于设计和实现高并发、低延迟的网络服务至关重要。本文将深度剖析阻塞式I/O&#xff08;BIO&…

OpenHarmony轻量系统开发【5】驱动之GPIO点灯

5.1点灯例程源码 先看最简单得LED灯闪烁操作 源码结构如下&#xff1a; 第一个BUILD.gn文件内容&#xff1a; static_library("led_demo") {sources ["led_demo.c"]include_dirs ["//utils/native/lite/include","//kernel/liteos_m/c…

Oracle解析exp、imp及常见的问题

前言 在工作中经常需要不同数据库的导入和导出。exp和imp可以实现数据的迁移。 exo会转储产生对应的二进制文件,里面包括数据的定义信息、数据内容等,即为dump文件。 下面是使用exp和imp的一些场景 exp和imp主要有4中模式: 1)数据库模式 数据库模式也就是我们说的全备…