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

基于C++(MFC)实现的文件管理系统

基于 MFC 的文件管理系统

第一章 题目解读与要求分析

1 实习题目

实现一个文件系统。

2 功能要求

界面上显示树形目录结构

a)根节点是“我的电脑”

b)“我的电脑”下有几个盘符(C、D、E 等)就有几个子节点,递归显 示文件系统下的所有文件信息(分支可以是目录也可以是文件,叶 子节点都是文件)

能够创建目录、创建文件、删除目录、删除文件、复制文件、粘贴文件

3 界面要求

界面要友好,让用户操作使用起来非常方便。

第二章 需求分析

1 问题描述

由题目以及题目功能要求与界面要求可知,这一题首先要求我们能够获取电脑本地的所有盘符;然后利用递归将本地的所有文件夹以及文件都获取到;接着将获取到的所有内容以树形目录结构的形式在 UI 界面显示,并且任一文件夹中的内容(文件夹、文件)可以以列表的形式在 UI 界面显示出来,以此来给用户较好的体验;最后在写出的可视化界面上要能够对文件夹或者文件进行创建、删除、复制、粘贴等操作,这些操作应以可视化的形式显示并且要足够简单,让用户操作使用起来足够方便。

由上述描述分析可知,本题要求做出一个功能类似 Windows 10 操作系统中的“此电脑”的可视化应用程序,故可以仿照“此电脑”的 UI 设计及相关功能的操作方法。

2 系统环境

操作系统:Windows 10

编程语言:C++(MFC)

开发环境及编译器:VisuaStudio 2019 + MFC(C++ 的 API)

硬件:除分好盘的硬盘空间外,能够流畅运行 VS2019 的基础硬件即可

3 运行要求

VS2019 里面配置 MFC

新建 MFC 项目

若无此项,拖动到底部安装相关工具和功能

若已配置好环境,就可以在 vs 里面直接打开项目

第三章 软件设计与实现

1 数据结构和存储结构的设计

因为这个文件系统的程序需要实时读取当前磁盘空间的存储状态及存储内容并且在 C++ 中具有读取文件或文件夹状态以及路径的 API 函数,所以在程序中对于文件或文件夹的操作并不需要其他什么特殊的数据结构和存储结构,只要在使用树控件的时候利用现成的 API 获取相应的信息并将这些信息在树形控件中显示出来即可。

若想存储文件或文件夹的信息,可以采用树结构来存储,一个结点的孩子结点是这个结点所代表的文件夹中的所有文件或者其他文件夹,其中文件一定处在叶子结点上;其次,为了查询的方便、快速以及 IO 开销尽可能小,可以采用 B-树或者 B+ 树的结构存储,可以减小 IO 开销,提高查询效率。

其他的一些数据结构,例如栈、堆、队列、数组等,用法、设计与其余所有 C++ 程序相同。(比如调用函数,利用了堆栈等)

2 算法设计

递归算法

1、获取所有盘符的下一级目录

2、删除目录及目录中的所有内容,要删除一个目录首先要删除该目录下的所有文件和文件夹,然后再移除空文件夹,同样删除该文件夹下的文件夹也需要先删除其中的文件和文件夹,就形成了递归。

bool CFileSystemDlg::DeleteFolder(LPCTSTR pstrFolder)
{// TODO: 在此处添加实现代码.if ((NULL == pstrFolder)){return FALSE;}/*检查输入目录是否是合法目录*/if (!IsDirectory(pstrFolder)){return FALSE;}/*创建源目录中查找文件的通配符*/CString strWildcard(pstrFolder);if (strWildcard.Right(1) != _T('\\')){strWildcard += _T("\\");}strWildcard += _T("*.*");/*打开文件查找,查看源目录中是否存在匹配的文件*//*调用FindFile后,必须调用FindNextFile才能获得查找文件的信息*/CFileFind finder;BOOL bWorking = finder.FindFile(strWildcard);while (bWorking){/*查找下一个文件*/bWorking = finder.FindNextFile();/*跳过当前目录“.”和上一级目录“..”*/if (finder.IsDots()){continue;}/*得到当前目录的子文件的路径*/CString strSubFile = finder.GetFilePath();/*判断当前文件是否是目录,*//*如果是目录,递归调用删除目录,*//*否则,直接删除文件*/if (finder.IsDirectory()){if (!DeleteFolder(strSubFile)){finder.Close();return FALSE;}}else{if (!DeleteFile(strSubFile)){finder.Close();return FALSE;}}} /*while (bWorking)*//*关闭文件查找*/finder.Close();/*删除空目录*/return RemoveDirectory(pstrFolder);
计数器累加判断是否已存在的算法

每一次需要创建文件或者文件夹,都从 1 开始若文件或文件夹已存在计数器就加 1,形成新的文件夹或文件的名称,直到没有重复时就以该名称创建文件或文件夹。

文件夹:

str += _T("新建文件夹1");while (PathIsDirectory(str)) {str.Delete(str.GetLength() - 1, 1);CString chg;chg.Format(_T("%d"), f_cnt);str += chg;f_cnt++;}

文本文档:

str += _T("新建文本文档1.txt");while (PathFileExists(str)) {CString chg;chg.Format(_T("%d"), t_cnt);str.SetAt(str.Find(_T(".")) - 1, chg.GetAt(0));t_cnt++;}CFile file(str, CFile::modeCreate);file.Close();

DOCX 文档:

str += _T("新建DOCX文档1.docx");while (PathFileExists(str)) {CString chg;chg.Format(_T("%d"), d_cnt);str.SetAt(str.Find(_T(".")) - 1, chg.GetAt(0));d_cnt++;}CFile file(str, CFile::modeCreate);file.Close();
读取一个文件夹下的所有文件或文件夹的算法

运用 MFC 中的 CFileFind 类中的 FindFile(str)获取一个文件夹下面的所有文件和文件夹。

运用MFC中的CFileFind类中的FindFile(str)获取一个文件夹下面的所有文件和文件夹。
CFileFind file;BOOL bContinue = file.FindFile(str);while (bContinue) {bContinue = file.FindNextFileW();if (!file.IsDots()) {					//文件和文件夹SHFILEINFO info = { 0 };CString temp = str;int index = temp.Find(_T("*.*"));temp.Delete(index, 3);SHGetFileInfo(temp + file.GetFileName(), 0, &info, sizeof(&info), SHGFI_DISPLAYNAME | SHGFI_ICON);int i = m_ImageList.Add(info.hIcon);m_list.SetImageList(&m_ImageList, LVSIL_SMALL);	//设置图标m_list.InsertItem(i, info.szDisplayName, i);		//在列表插入一项}}

3 模块设计

树形控件显示模块

1、获取所有盘符并在树形控件中的根节点“我的电脑”的孩子结点上插入:

void CFileSystemDlg::GetLogicalDrive(HTREEITEM hParent)

2、获取所有盘符下的所有文件夹并在相应盘符结点的孩子结点上插入(仅仅是盘符的下一级):

void CFileSystemDlg::GetDriveDir(HTREEITEM hParent)

注:盘符的下一级单独处理的原因是盘符与普通文件夹不同需要单独处理。

3、返回某一结点的绝对路径(从结点开始向根节点回溯):

CString CFileSystemDlg::GetFullPath(HTREEITEM hCurrent)

4、获取某一文件夹下的所有文件夹并在代表该文件夹的结点的孩子结点上插入子文件夹:

void CFileSystemDlg::AddSubDir(HTREEITEM hParent)

5、展开树形控件某一结点时触发的事件(显示该节点下的所有文件夹并载入再下一层的文件夹):

void CFileSystemDlg::OnItemexpandedTree(NMHDR pNMHDR, LRESULT pResult)

列表控件显示模块

1、选择树形控件的某一节点时触发的事件(将该结点代表的文件下的所有文件夹以及文件显示在列表控件中):

void CFileSystemDlg::OnSelchangedTree(NMHDR pNMHDR, LRESULT pResult)

2、鼠标左键双击列表控件时触发的事件(文件夹:打开该文件夹在列表控件中显示;文件:调用外部应用程序打开文件)(未选中任何一项无动作):

void CFileSystemDlg::OnDblclkList(NMHDR pNMHDR, LRESULT pResult)

3、鼠标右键单击列表控件时触发的事件(选中了某一项时显示操作菜单:打开、复制、删除;未选中某一项时显示操作菜单:刷新、新建、粘贴):

void CFileSystemDlg::OnRclickList(NMHDR pNMHDR, LRESULT pResult)

返回、转到与显示地址模块

1、单击“返回”按钮时触发的事件(返回上一级目录):

void CFileSystemDlg::OnClickedBack()

2、单击“转到”按钮时触发的事件(进入下拉列表框中输入的路径所表示的文件夹内):

void CFileSystemDlg::OnClickedEnter()

3、下拉列表框中所选项发生变化时所触发的事件(进入下拉列表框所选项表示的文件夹内):

void CFileSystemDlg::OnSelchangeDirpath()

创建模块

注:文件、文件夹的命名均通过计数器来避免名称冲突而创建失败。

1、鼠标右键单击列表空白处后弹出菜单,再鼠标左键单击菜单的“新建-文件夹”时触发的事件(在操作的目录下新建一个文件夹):

void CFileSystemDlg::OnNewfile()

2、鼠标右键单击列表空白处后弹出菜单,再鼠标左键单击菜单的“新建-文本文档”时触发的事件(在操作的目录下新建一个文本文档):

void CFileSystemDlg::OnTxt()

3、鼠标右键单击列表空白处后弹出菜单,再鼠标左键单击菜单的“新建-DOCX 文档”时触发的事件(在操作的目录下新建一个 DOCX 文档):

void CFileSystemDlg::OnDocx()

删除模块

1、判断一个路径是否是已存在的文件夹

booCFileSystemDlg::IsDirectory(LPCTSTR pstrPath)

2、删除文件夹及文件夹中的所有内容

booCFileSystemDlg::DeleteFolder(LPCTSTR pstrFolder)

3、选中列表中的某一项后鼠标右键单击后弹出菜单,再鼠标左键单击菜单的“删除”时触发的事件(删除选中的文件夹或者文件):

void CFileSystemDlg::OnDelete()

注:如果删除的是文件可以直接调用 mfc 的函数来删;如果删除的是文件夹,那么就需要先删除该文件夹下所有的文件夹以及文件后再移除该空文件夹(递归思想)。

复制模块

1、将参数(要复制的文件或文件夹的绝对路径)赋给成员变量 dir_path:

void CFileSystemDlg::CopyToClipboard(CString dirPath)

2、选中列表中的某一项后鼠标右键单击后弹出菜单,再鼠标左键单击菜单的“复制”时触发的事件(得到选中项的绝对路径赋给成员变量 dir_path)(在事件处理中调用

CopyToClipboard(dirPath)函数:

void CFileSystemDlg::OnCopy()

注:将要复制的文件或文件夹的绝对路径赋给成员变量 dir_path 是为了在粘贴时调用

CopyFile(dir_path, dirPath, TRUE)函数。

粘贴模块

1、将经过上述复制操作的文件或者文件夹粘贴到参数 dirPath 目录下:

void CFileSystemDlg::PasteToFile(CString dirPath)

2、鼠标右键单击列表空白处后弹出菜单,再鼠标左键单击菜单的“粘贴”时触发的事件(在操作的目录下粘贴已复制的文件或者文件夹):

void CFileSystemDlg::OnPaste()

注:粘贴文件夹时是先创建一个文件夹,然后再在这个新创建的文件夹里面粘贴文件,嵌套(递归)。

4 类的函数成员和数据成员设计

注:在程序中主要是在 CFileSystemDlg 类进行编程,所以另外两个自动生成的类这里不做赘述,下面是 CFileSystemDlg 类的类定义,其中用到的数据成员都给了注释,而用到的成员函数在上一节“模块设计”小节以及本章最后一小节“其他模块设计与实现”小节中已经说明。

CFileSystemDlg 类的定义
// CFileSystemDlg 对话框
class CFileSystemDlg : public CDialogEx
{
// 构造
public:CFileSystemDlg(CWnd* pParent = nullptr);	// 标准构造函数// 对话框数据
# ifdef AFX_DESIGN_TIMEenum { IDD = IDD_FILESYSTEM_DIALOG };
# endifprotected:virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持// 实现
protected:HICON m_hIcon;		// 图标// 生成的消息映射函数virtual BOOL OnInitDialog();	// 初始化操作afx_msg void OnSysCommand(UINT nID, LPARAM lParam);afx_msg void OnPaint();afx_msg HCURSOR OnQueryDragIcon();DECLARE_MESSAGE_MAP()
public:CListCtrl m_list;				// 列表控件CTreeCtrl m_tree;				// 树形控件CComboBox m_combo;				// 下拉列表框控件(起到桥梁作用,传递路径)
protected:HTREEITEM m_hRoot;				// CTreeCtrl控件的项句柄,在树中标识唯一一									//个节点是一个DWORD值CImageList m_ImageList;			//树结点文字内容前面的图标控件CString dir_path;				//保存需要复制的文件或者文件夹的绝对路径int f_cnt;						//新建文件夹避免重名用到的计数器int t_cnt;						//新建文本文档避免重名用到的计数器int d_cnt;						//新建DOCX文档避免重名用到的计数器
public:void GetLogicalDrive(HTREEITEM hParent);void GetDriveDir(HTREEITEM hParent);CString GetFullPath(HTREEITEM hCurrent);void AddSubDir(HTREEITEM hParent);afx_msg void OnItemexpandedTree(NMHDR* pNMHDR, LRESULT* pResult);afx_msg void OnSelchangedTree(NMHDR* pNMHDR, LRESULT* pResult);afx_msg void OnDblclkList(NMHDR* pNMHDR, LRESULT* pResult);afx_msg void OnOpen();afx_msg void OnRclickList(NMHDR* pNMHDR, LRESULT* pResult);afx_msg void OnCopy();afx_msg void OnDelete();afx_msg void OnNewfile();afx_msg void OnTxt();// 更新ListCtrlvoid Refresh(CString str);afx_msg void OnDocx();afx_msg void OnRefresh();afx_msg void OnPaste();bool DeleteFolder(LPCTSTR pstrFolder);bool IsDirectory(LPCTSTR pstrPath);afx_msg void OnClickedBack();afx_msg void OnClickedEnter();afx_msg void OnSelchangeDirpath();void CopyToClipboard(CString dirPath);void PasteToFile(CString dirPath);
};

5 界面设计

采用 MFC 的基于对话框的界面设计

将默认生成的确定和取消按钮删除

调整好对话框的大小

在对话框中添加两个 GroupBox 控件,并将他们的 Caption 属性分别改为“文件目录”和“文件列表”

添加树形控件 Tree Control,设置相关属性

添加列表控件 ListBox,设置相关属性

添加两个按钮控件 Button,分别实现返回和转到的功能

添加下拉列表框控件 Combo Box,设置相关属性

6 其它模块设计与实现

界面刷新模块

1、更新参数 strTemp(绝对路径)目录在列表控件中的显示(在删除、新建、粘贴事件中均会调用这个函数):

// 更新ListCtrl
void CFileSystemDlg::Refresh(CString strTemp)
{// TODO: 在此处添加实现代码.if (GetFileAttributes(strTemp) & FILE_ATTRIBUTE_DIRECTORY) {//m_combo.DeleteString(0);m_combo.InsertString(0, strTemp);m_combo.SetCurSel(0);if (strTemp.Right(1) != "\\") {strTemp += "\\";}strTemp += "*.*";CFileFind file;BOOL bContinue = file.FindFile(strTemp);m_list.DeleteAllItems();while (bContinue) {bContinue = file.FindNextFileW();if (!file.IsDots()) {SHFILEINFO info = { 0 };CString temp = strTemp;int index = temp.Find(_T("*.*"));temp.Delete(index, 3);SHGetFileInfo(temp + file.GetFileName(), 0, &info, sizeof(&info), SHGFI_DISPLAYNAME | SHGFI_ICON);int i = m_ImageList.Add(info.hIcon);m_list.SetImageList(&m_ImageList, LVSIL_SMALL);m_list.InsertItem(i, info.szDisplayName, i);}}}else {if (PathFileExists(strTemp))ShellExecute(NULL, TEXT("OPEN"), strTemp, NULL, NULL, SW_SHOWNORMAL);	//调用外部程序打开文件}
}

2、鼠标右键单击列表空白处后弹出菜单,再鼠标左键单击菜单的“刷新”时触发的事件(在操作的目录下更新显示的列表控件中的内容):

void CFileSystemDlg::OnRefresh()
{// TODO: 在此添加命令处理程序代码CString strTemp;m_combo.GetWindowText(strTemp);if (strTemp.Right(1) != "\\") {strTemp += "\\";}Refresh(strTemp);

第四章 调试分析

1 主要问题及解决方案

树形控件与列表控件之间的信息传递问题

问题:在列表控件的事件处理中如何获得操作的绝对路径,并在此基础上进行更复杂的操作?

分析:选择树形控件的某一节点之后,会在列表控件中显示该节点所表示的文件夹内的所有内容。此时,如果不保留所选节点的绝对路径,那么只能得到该节点所代表的文件夹内的所有内容的名称,而丢失他们的绝对路径,堆在列表控件中要进行的新建、删除、复制、粘贴等操作就无从下手(这些操作都需要相应文件夹或者文件的绝对路径)。

解决方案:首先可以想到在类的成员变量中设置一个存放当前列表控件所显示的目录的绝对路径,并在各种操作中获取或更新这个成员变量,这种方案是可行的;但是还有一种更加方便快捷的方案:利用 Combo Box 下拉列表控件,在选择树形控件的某一节点进行事件处理时,在 Combo Box 中插入当前展示的目录的绝对路径并展示出来,这样以后在列表控件中需要使用用绝对路径的时候,只要在 Combo Box 控件中获取即可。

1 处将路径插入下拉列表框的列表中,2 处将刚刚插入的内容显示出来。

复制、粘贴的实现问题

问题:如何复制粘贴?利用剪贴板和直接采用 MFC 的 API 哪个好?

分析:复制粘贴有两种思路。第一,利用系统的剪贴板,将要复制的文件放到剪贴板上取,然后在粘贴的时候,从剪贴板上获取之后粘贴(看似比较可行);第二,利用 MFC 的 API,直接通过需要复制的文件的绝对路径和要复制到的绝对路径,调用 CopyFile(source, destination, TRUE)直接复制(看似笨重,很不灵活)。开始死钻第一种思路,结果发现文件的类型多样并且文件夹嵌套较多,处理起来十分困难,网上也没有找到相关的教程,似乎走进了死胡同。这时,回头看一看第二种思路,发现只要稍微变通一下:在复制的时候只将文件或者文件夹的绝对路径保存下来(这里采用数据成员的方式进行保存),然后在粘贴的时候,可以获取要粘贴到文件夹的绝对路径,再进行一些处理,即可利用 CopyFile(source, destination, TRUE)直接将文件复制粘贴过去。

解决方案:在复制的时候只将文件或者文件夹的绝对路径保存下来(这里采用数据成员的方式进行保存),然后在粘贴的时候,可以获取要粘贴到文件夹的绝对路径,再进行一些处理,即可利用 CopyFile(source, destination, TRUE)直接将文件复制粘贴过去。

2 设计和编码的回顾讨论和分析

整个程序是以 mfc 的可视化对话框为中心来设计编码的,通过对控件控件成员的操作以及一些适当的辅助成员的利用,可以完美实现题目中要求的大部分功能。

在编码时,结合帮助文档以及一些博客的讲解,熟悉掌握 CFile、CString、CFileFind 等类的基本使用方法,对绝对路径的字符串进行操作以及对文件和文件夹的操作,能够写出这样的程序。

熟悉 MFC 的时间处理机制,与 QT 的信号与槽进行对比(虽然大一下学期做大作业的时候学的 QT 知识已经忘的差不多了)。

3 算法的时间和空间复杂度的分析

主要的算法都是直接调用 MFC 中封装好的 API,故算法的时间复杂度和空间复杂度基本上就是 API 函数的复杂度。

同样也没有特别的空间复杂度。

以下为最坏时间复杂度:

void GetLogicalDrive(HTREEITEM hParent);//O(盘符个数)void GetDriveDir(HTREEITEM hParent);//O(盘符个数×平均盘符下的文件和文										//件夹的数量)CString GetFullPath(HTREEITEM hCurrent);//O(树结点所在的层数)void AddSubDir(HTREEITEM hParent);//O(文件夹下的文件夹和文件之和)afx_msg void OnItemexpandedTree(NMHDR* pNMHDR, LRESULT* pResult);
//O(所展开节点下一层目录中的所有文件夹及其子文件夹的个数)afx_msg void OnSelchangedTree(NMHDR* pNMHDR, LRESULT* pResult);
//O(选择的节点所代表的文件夹下的所有文件和文件夹之和)afx_msg void OnDblclkList(NMHDR* pNMHDR, LRESULT* pResult);
//O(选择的文件夹下的所有文件和文件夹之和)
afx_msg void OnOpen();//O(选择的文件夹下的所有文件和文件夹之和)afx_msg void OnRclickList(NMHDR* pNMHDR, LRESULT* pResult);
//O(展示弹出菜单的时间复杂度)afx_msg void OnCopy();//O(1)afx_msg void OnDelete();//O(要删除的文件夹下的所有文件和										//文件夹之和与删除的文件夹所在文件夹内文件							//和文件夹之和的最大值)
afx_msg void OnNewfile();//O(新建文件夹所在文件夹下的所有文件和文件夹							//之和)
afx_msg void OnTxt();//O(新建文本文档所在文件夹下的所有文件和文件夹							//之和)
void Refresh(CString str);//O(刷新所在文件夹下的所有文件和文件夹之和)
afx_msg void OnDocx();//O(新建DOCX文档所在文件夹下的所有文件和文件夹							//之和)afx_msg void OnRefresh();//O(刷新所在文件夹下的所有文件和文件夹之和)afx_msg void OnPaste();//O(需要复制的文件夹下的所有文件和文								  //件夹之和与粘贴到的文件夹内所有文件和文件夹之						  //和的最大值)bool DeleteFolder(LPCTSTR pstrFolder);//O(要删除的文件夹下的所有文件和										  //文件夹之和)bool IsDirectory(LPCTSTR pstrPath);//O(1)afx_msg void OnClickedBack();//O(上一级目录中文件和文件夹的和)afx_msg void OnClickedEnter();//O(所输入目录中文件和文件夹的和)afx_msg void OnSelchangeDirpath();//O(所选择目录中文件和文件夹的和)void CopyToClipboard(CString dirPath);//O(1)void PasteToFile(CString dirPath);//O(需要复制的文件夹下的所有文件和文									  //件夹之和,一直到叶节点)

4 算法的进一步改进

计数器累加判断是否已存在的算法

原本的算法中采用了计数器来避免重复的文件或者文件夹的名称,但是计数器仍然存在一些问题,在原先的程序中,计数器只有递增而没有递减,所以在删除掉一些文件或者文件夹之后,会出现有的下标没有用到,造成顺序问题。

其实可以改进一下,不用计数器。每次新建都直接从 1 开始判断,都从 1 开始递增,通过循环,找到第一个空缺的下标并把它利用起来即可。

str += _T("新建DOCX文档1.docx");while (PathFileExists(str)) {int n = 2;CString chg;chg.Format(_T("%d"), n);str.SetAt(str.Find(_T(".")) - 1, chg.GetAt(0));n++;}CFile file(str, CFile::modeCreate);file.Close();

复制粘贴功能利用系统剪贴板实现

本程序中的复制粘贴功能利用 CopyFile(dir_path, dirPath, TRUE);函数实现,若采用系统剪贴板,自定义类型可能会更好。

文件或者文件夹重命名

本程序不能进行文件或者文件夹的重命名,若能够进行重命名将能够更加方便用户使用。

在调试的过程中出现了四个警告并且程序最终返回值不为 0(为 2)

四个警告是数据溢出,可能是空间的 ID 号设置的太大溢出了宏定义的范围。

开始通过修改控件的 ID 号可以解决这个问题,然而再次打开时又出现了该警告。

返回值不为 0,应该是哪里出问题了。

第五章 实习心得

在为期一周的实训中,我学到了很多。从拿到题目的那一刻的模模糊糊到开始着手设计、深入的愈渐明朗到最终完成开发,这其中有成功的喜悦,也有失败的泄气,恰恰也正是在这样一个过程中,我学到了很多。

在开发一个程序的过程中遇到各种各样的问题是在所难免的,这就需要我们不断地去学习,去找博客,去吸收前辈们的经验。这次我使用的 MFC 是我这之前从未接触过的一个框架,但是在边学边写的过程中,我能够基本熟练使用这个框架。

当然,在这次实训中,我更深一步地了解和学习了软件开发的一般过程,从题目解读到需求分析再到设计和编码实现,经历了一个完整的开发过程,在以后的开发中我相信我能够更加熟练。

相关文章:

基于C++(MFC)实现的文件管理系统

基于 MFC 的文件管理系统 第一章 题目解读与要求分析 1 实习题目 实现一个文件系统。 2 功能要求 界面上显示树形目录结构 a)根节点是“我的电脑” b)“我的电脑”下有几个盘符(C、D、E 等)就有几个子节点,递归…...

selenium 实现模拟登录中的滑块验证功能

用python在做数据采集过程中,经常需要用到模拟登录,经常遇到各种图片、文字甚至短信等验证,如果能通过脚本的方便实现验证,就可以自动帮我更高效地收集数据。Selenium 是一个开源的 Web 自动化测试工具,最初是为网站自…...

Oracle 19c部署之数据库软件安装(二)

在完成了Oracle Linux 9的初始化配置之后,我们准备安装Oracle 19c数据库软件。 Oracle数据库支持两种主要的安装方式:图形化安装和静默安装。这两种方法各有优缺点,选择哪种取决于你的具体需求、环境配置以及个人偏好。 图形化安装 图形化安…...

Paramiko 使用教程

目录 简介安装 Paramiko连接到远程服务器执行远程命令文件传输示例 简介 Paramiko 是一个基于 Python 的 SSH 客户端库,它提供了在网络上安全传输文件和执行远程命令的功能。本教程将介绍 Paramiko 的基本用法,包括连接到远程服务器、执行命令、文件传输…...

从EOF到REOF:如何用旋转经验正交函数提升时空数据分析精度?

目录 1. 基本概念与原理2. 应用场景3. 与传统EOF的区别4. 技术实现5. 其他领域中的“REOF”参考资料 REOF 的输入是多个地区在不同时间的气候数据(如温度或降雨量),它的作用是通过旋转计算找出这些数据中最主要的变化规律,输出则是…...

VS-Code创建Vue3项目

1 创建工程文件 创建一个做工程项目的文件夹 如:h5vue 2 cmd 进入文件 h5vue 3 输入如下命令 npm create vuelatest 也可以输入 npm create vitelatest 4 输入项目名称 项目名称:自已输入 回车 可以按键盘 a (全选) 回车: Playwright…...

JESD204B接收器核心实现和系统级关键细节

目录 1.通道偏移 2.弹性缓冲器的实现 3.接受延迟 4.RX端到端延迟 5.计算端到端延迟 6.实现可重复的延迟 1.通道偏移 JESD204B接收器核心已经过验证,其功能具有高达8个字节的通道到通道偏斜。 2.弹性缓冲器的实现 在JESD204B设备中,接收通道对齐弹性缓冲区是在分布式…...

NLP高频面试题(四十七)——探讨Transformer中的注意力机制:MHA、MQA与GQA

MHA、MQA和GQA基本概念与区别 1. 多头注意力(MHA) 多头注意力(Multi-Head Attention,MHA)通过多个独立的注意力头同时处理信息,每个头有各自的键(Key)、查询(Query)和值(Value)。这种机制允许模型并行关注不同的子空间上下文信息,捕捉复杂的交互关系。然而,MHA…...

k230学习笔记-疑难点(1)

1.出现boot failed with exit code 19: 需要将k230开发板的btoot0拨到ON 2.出现boot failed with exit code 13: 说明k230开发板的固件烧录已经丢失,需要重新烧录 *** 注意重新烧录时需要将btoot0重新拨到OFF,才会弹出加载固件需要的通用串行总线&…...

JavaScript性能优化实战:让你的Web应用飞起来

JavaScript性能优化实战:让你的Web应用飞起来 在前端开发中,JavaScript性能优化是提升用户体验的关键。一个性能良好的应用不仅能吸引用户,还能提高转化率和用户留存率。今天,我们就来深入探讨JavaScript性能优化的实战技巧&…...

金融数据库转型实战读后感

荣幸收到老友太保科技有限公司数智研究院首席专家林春的签名赠书。 这是国内第一本关于OceanBase数据库实际替换过程总结的的实战书。打个比方可以说是从战场上下来分享战斗经验。读后感受颇深。我在这里讲讲我的感受。 第三章中提到的应用改造如何降本。应用改造是国产化替换…...

血脂代谢通路(医学-计算机系统对照方式)

血脂代谢通路(医学-计算机系统对照方式) 整合所有类比,用医学-计算机系统对照的方式完整描述血脂代谢通路,采用分步骤的对照结构: 1. 食物摄入(数据输入层) # 医学术语: 膳食脂肪摄入 → 计算机类比: 原始数据输入 …...

git更新的bug

文章目录 1. 问题2. 分析 1. 问题 拉取了一个项目后遇到了这个问题, nvocation failed Server returned invalid Response. java.lang.RuntimeException: Invocation failed Server returned invalid Response. at git4idea.GitAppUtil.sendXmlRequest(GitAppUtil…...

直流电源基本原理

整流电路 在构建整流电路时,要选择合适参数的二极管 If是二极管能够通过电流的能力,也是最大整流的平均电流。 还要考虑二极管的反向截至电压。 脉动系数电压交流幅值/直流平均电压(越小越好) 三相整流电路优点: …...

Git -> git merge --no-ff 和 git merge的区别

git merge --no-ff <branch> 与 git merge <branch> 的区别 核心区别 git merge <branch>: 默认使用Fast-forward模式&#xff08;若可行&#xff09;不创建额外的合并提交记录合并后看不出曾经存在过分支 git merge --no-ff <branch>:强制创建一个…...

名胜古迹传承与保护系统(springboot+ssm+vue+mysql)含运行文档

名胜古迹传承与保护系统(springbootssmvuemysql)含运行文档 名胜古迹传承与保护系统是一个专注于文化遗产保护和管理的综合性平台。系统提供了一系列功能模块&#xff0c;包括名胜古迹管理、古迹预约管理、古迹故事管理、举报信息管理、保护措施管理、古迹讨论、管理员管理、版…...

windows资源管理器左边导航窗格增加2个项,windows10/11有效

下面文档存为.reg文件&#xff0c; Windows Registry Editor Version 5.00; 根 CLSID —— 名称、图标、固定到导航窗格 [HKEY_CURRENT_USER\Software\Classes\CLSID\{C1A3F2D2-BD2D-4D60-82C5-394F01753A5F}] "手机系统" "System.IsPinnedToNamespaceTree&quo…...

【八股文】基于源码聊聊ConcurrentHashmap的设计

版本演进 jdk 1.7中是分段锁的设计&#xff0c;将哈希表划分为多个segment&#xff0c;每个段独立加锁&#xff0c;锁粒度为段级别。 操作需两次哈希&#xff0c;第一次定位段&#xff0c;第二次定位桶内链表。这种实现方式的缺点就是段数量固定&#xff0c;扩容复杂&#xf…...

Mysql--基础知识点--93--两阶段提交

1 两阶段提交 以update语句的具体执行过程为例&#xff1a; 具体更新一条记录 UPDATE t_user SET name ‘xiaolin’ WHERE id 1;的流程如下&#xff1a; 1.执行器负责具体执行&#xff0c;会调用存储引擎的接口&#xff0c;通过主键索引树搜索获取 id 1 这一行记录&#…...

数字化招标采购系统怎么让招采协同更高效?

招标采购领域的数智化转型正在引发行业革命性变革。从传统线下模式到全流程电子化&#xff0c;再到当前数智化阶段的超时空协同&#xff0c;行业的演进路径清晰展现了技术与管理的深度融合。郑州信源信息数智化招采系统作为行业标杆&#xff0c;其创新实践为未来协同工作方式的…...

池塘计数(BFS)

题目描述 由于最近的降雨&#xff0c;光头强的田地里的各个地方都积水了&#xff0c;用 NM(1≤N≤100&#xff1b;1≤M≤100)NM(1≤N≤100&#xff1b;1≤M≤100) 的正方形的矩形表示。每个广场都有水 W 或旱地 .。光头强想知道他的田地里形成了多少池塘。池塘是指一组相邻的有…...

《Science》观点解读:AI无法创造真正的智能体(AI Agent)

无论是想要学习人工智能当做主业营收&#xff0c;还是像我一样作为开发工程师但依然要运用这个颠覆开发的时代宠儿&#xff0c;都有必要了解、学习一下人工智能。 近期发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;入行门槛低&#x…...

从零开始学A2A四:A2A 协议的安全性与多模态支持

文章目录 A2A 协议的安全性与多模态支持一、A2A 协议安全机制1. 认证机制2. 授权机制3. 数据加密 二、多模态交互支持1. 文本交互2. 音频支持3. 视频与图像处理4. 复合数据格式 三、安全与多模态最佳实践1. 安全性实践2. 多模态实践 四、与 MCP 的对比1. 安全机制对比2. 多模态…...

一种大位宽加减法器的时序优化

平台&#xff1a;vivado2018.3 芯片&#xff1a;xc7a100tfgg484-2 (active) 在FPGA中实现超高位宽加减法器&#xff08;如256&#xff09;时&#xff0c;时序收敛常成为瓶颈。由于进位链&#xff08;Carry Chain&#xff09;跨越多级逻辑单元&#xff0c;关键路径延迟会随位宽…...

【专业解读:Semantic Kernel(SK)】大语言模型与传统编程的桥梁

目录 Start:什么是Semantic Kernel&#xff1f; 一、Semantic Kernel的本质&#xff1a;AI时代的操作系统内核 1.1 重新定义LLM的应用边界 1.2 技术定位对比 二、SK框架的六大核心组件与技术实现 2.1 内核&#xff08;Kernel&#xff09;&#xff1a;智能任务调度中心 2…...

InfiniBand与RoCEv2负载均衡机制的技术梳理与优化实践

AI技术的高速迭代正驱动全球算力格局进入全新纪元。据IDC预测&#xff0c;未来五年中国智能算力规模将以超50%的年复合增长率爆发式扩张&#xff0c;数据中心全面迈入“智能算力时代”。然而&#xff0c;海量AI训练、实时推理等高并发场景对底层网络提出了更严苛的挑战——超大…...

Vue与React组件化设计对比

组件化是现代前端开发的核心思想之一&#xff0c;而Vue和React作为两大主流框架&#xff0c;在组件化设计上既有相似之处&#xff0c;也存在显著差异。本文将从语法设计、数据管理、组件通信、性能优化、生态系统等多个方向&#xff0c;结合实例详细对比两者的特点。 一、模板…...

UE中通过AAIController::MoveTo函数巡逻至目标点后没法正常更新巡逻目标点

敌人巡逻的逻辑如下&#xff1a; 敌人在游戏一开始的时候就通过moveto函数先前往首先设定的patroltarget目标&#xff0c;在距离patroltarget距离为patroradius&#xff08;200unit)之内时就可以通过checkpatroltarget函数更新新的patroltarget目标&#xff0c;随后前往新的pat…...

Python-细节知识点range函数的详解

在 Python 中&#xff0c;range 是一个内置函数&#xff0c;用于生成一个不可变的整数序列&#xff0c;通常用于控制循环次数或生成数值范围。以下是详细说明&#xff1a; 基本语法 range(stop) # 生成 [0, stop) 的整数&#xff0c;步长为1 range(start, stop) …...

git rebase的使用

我的使用 git checkout feature # 本地分支 git pull origin main --rebase # 目标分支 git pull origin feature --rebase git push origin featuregit rebase 是 Git 中用于重写提交历史的强大工具&#xff0c;可将分支的提交移动到新的基点上&#xff0c;使历史更线性。以…...

CMake Error at build/_deps/glog-src/CMakeLists.txt:1 (cmake_minimum_required):

这个错误提示意思是你当前系统上安装的 CMake 版本过低&#xff0c;不满足项目的要求。根据错误信息&#xff1a; CMake Error at build/_deps/glog-src/CMakeLists.txt:1 (cmake_minimum_required): CMake 3.22 or higher is required. You are running version 3.16.3 项目…...

MATLAB 控制系统设计与仿真 - 34

多变量系统知识回顾 - MIMO system 这一章对深入理解多变量系统以及鲁棒分析至关重要 首先&#xff0c;对于如下系统&#xff1a; 当G(s)为单输入&#xff0c;单输出系统时&#xff1a; 如果&#xff1a; 则&#xff1a; 所以 当G(s)为MIMO时&#xff0c;例如2X2时&#xff…...

【Unity】JSON数据的存取

这段代码的结构是为了实现 数据的封装和管理&#xff0c;特别是在 Unity 中保存和加载玩家数据时。以下是对代码设计的逐步解释&#xff1a; 1. PlayerCoin 类 PlayerCoin 是一个简单的数据类&#xff0c;用于表示单个玩家的硬币信息。它包含以下字段&#xff1a; count&…...

利用 Java 爬虫按关键字搜索淘宝商品

在电商领域&#xff0c;通过关键字搜索商品是常见的需求。淘宝作为国内知名的电商平台&#xff0c;提供了丰富的商品搜索功能。本文将详细介绍如何使用 Java 爬虫技术按关键字搜索淘宝商品&#xff0c;并获取搜索结果的详细信息。 一、准备工作 1. 注册淘宝开放平台账号 要使…...

【C】初阶数据结构11 -- 选择排序

本篇文章主要讲解经典排序算法 -- 选择排序 目录 1 算法思想 2 代码 3 时间复杂度与空间复杂度分析 1&#xff09; 时间复杂度 2&#xff09; 空间复杂度 1 算法思想 选择排序是一种在一段区间里面选择最小的元素和最大的元素的一种排序算法。假设这里排升序&#…...

【Semantic Kernel核心组件】Plugin:连接AI与业务逻辑的桥梁

目录 一、Plugin是什么&#xff1f;为什么它是SK的核心&#xff1f; 一、Plugin的核心机制与Python实现 1. 插件类型&#xff1a;语义函数与本地函数 语义函数&#xff08;Semantic Function&#xff09; 本地函数&#xff08;Native Function&#xff09; 2. Plugin的注…...

《基于神经网络实现手写数字分类》

《基于神经网络实现手写数字分类》 一、主要内容&#xff1a; 1、通过B站陈云霁老师的网课&#xff0c;配合书本资料&#xff0c;了解神经网络的基本组成和数学原理。 2、申请云平台搭建实验环境 3、基于5个不同的实验模块逐步理解实验操作步骤&#xff0c;并实现不同模块代码…...

车载诊断架构 --- 车载诊断概念的深度解读

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 周末洗了一个澡,换了一身衣服,出了门却不知道去哪儿,不知道去找谁,漫无目的走着,大概这就是成年人最深的孤独吧! 旧人不知我近况,新人不知我过…...

四、探索LangChain:连接语言模型与外部世界的桥梁

一、什么是 LangChain LangChain 是一个开源的软件框架,旨在帮助开发者高效构建和部署基于**大型语言模型(LLM)**的应用程序。它通过提供一系列工具、组件和接口,简化了从模型调用、提示工程到复杂应用开发的全流程,使得开发者能够快速将 LLM 集成到实际场景中。 1. 核心…...

LangChain4j中的Chat与语言模型API详解:构建高效对话系统的利器

LangChain4j中的Chat与语言模型API详解&#xff1a;构建高效对话系统的利器 引言&#xff1a;大模型时代的开发利器 在人工智能快速发展的今天&#xff0c;大型语言模型&#xff08;LLM&#xff09;已成为构建智能应用的核心组件。LangChain4j作为Java生态中领先的LLM集成框架…...

C++中const与constexpr的区别

在C中&#xff0c;const和constexpr都用于定义常量&#xff0c;但它们的用途和行为有显著区别&#xff1a; ### 1. **初始化时机** - **const**&#xff1a;表示变量是只读的&#xff0c;但其值可以在**编译时或运行时**初始化。 cpp const int a 5; // 编译…...

长亭2月公开赛Web-ssrfme

环境部署 拉取环境报错&#xff1a; 可以尝试拉取一下ubuntu:16.04&#xff0c;看是否能拉取成功 将wersion&#xff1a;"3"删掉 我拉去成功之后&#xff0c;再去拉取环境&#xff0c;成功&#xff01; 访问环境 测试ssrf 源码 <?php highlight_file(__file__…...

AI日报 - 2025年4月18日

&#x1f31f; 今日概览(60秒速览) ▎&#x1f916; AGI探讨 | 专家激辩AGI定义与实现时间点&#xff0c;Causal AI被视为关键一步&#xff0c;o3模型预测2027年实现引关注。 Causal AI强调因果关系而非模式&#xff1b;专家清单推荐不同模型适用场景&#xff1b;AGI定义及何时…...

Spring IoC 详解

在 Spring IoC& DI 详解 中对 IoC已经有了介绍&#xff0c;下面对 IoC 进行详细介绍。 IoC&#xff0c;即控制反转&#xff0c;在之前我们编写程序的时候&#xff0c;我们都是自己 new 出来一个对象&#xff0c;然后自己去管理这个对象&#xff0c;但是这有时候有些麻烦&a…...

oracle查询当前用户所有字段和表

在 Oracle 数据库中&#xff0c;可以通过查询数据字典视图来获取某个表的字段&#xff08;列&#xff09;信息。以下是常用的查询方法&#xff1a; 查询当前用户下的表字段 如果您想查看当前用户下某个表的字段信息&#xff0c;可以查询 USER_TAB_COLUMNS 视图&#xff1a; SE…...

ACL(访问控制列表)

ACL(访问控制列表&#xff09; 1、基础内容 访问控制列表ACL(Access ControlList)是由一条或多条规则组成的集合。所谓规则&#xff0c;是指描述报文匹配条件的判断语句&#xff0c;这些条件可以是报文的源地址、目的地址、端口号等。通过一系列规则来匹配报文&#xff0c;如…...

C语言数据结构---二叉树---堆的应用

1.建堆&#xff08;向上调整&#xff09; 1.1大堆 #include<stdio.h> void swap(int *p1,int *p2) {int temp *p1;*p1 *p2;*p2 temp; } void Ajustup(int *a,int child)//向上调整 {int parent (child - 1) / 2;while (child > 0){if (a[child] > a[parent]…...

在Linux下安装Gitlab

在Cenos7下安装GitLab 在ssh下安装 官方安装文档:https://gitlab.cn/install/?versionce 1. 使用阿里YUM 镜像云 下载 https://mirrors.aliyun.com/repo/Centos-7.repo替换 /etc/yum.repos.d/CentOS-Base.repo在目录/etc/yum.repos.d/下执行如下命令&#xff1a; curl …...

【算法】快速排序、归并排序(非递归版)

目录 一、快速排序&#xff08;非递归&#xff09; 1.原理 2.实现 2.1 stack 2.2 partition(array,left,right) 2.3 pivot - 1 > left 二、归并排序&#xff08;非递归&#xff09; 1.原理 2.实现 2.1 gap 2.1.1 i 2*gap 2.1.2 gap * 2 2.1.3 gap < array.…...

如何自学机器学习?零基础到实战的完整路径

机器学习作为人工智能的核心领域&#xff0c;已成为技术人必备的硬实力。本文为自学者梳理出一条从零基础到项目落地的系统学习路线&#xff0c;涵盖知识框架、工具链与实战技巧。 一、构建三大基础模块&#xff08;1-2个月&#xff09; 数学基石&#xff1a;线性代数重点掌握…...