C++课设:实现简易文件加密工具(凯撒密码、异或加密、Base64编码)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》
创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊)
专栏介绍:《编程项目实战》

目录

    • 一、初识文件加密:为什么需要保护我们的文件?
      • 1. 加密的基本概念
      • 2. 为什么选择这三种算法?
    • 二、工具介绍:三大经典加密算法一网打尽
      • 1. 凯撒密码(Caesar Cipher)
      • 2. 异或加密(XOR Encryption)
      • 3. Base64编码
      • 4. 环境兼容性说明
    • 三、核心代码实现:手把手教你构建加密工具
    • 四、实战演练:从入门到精通的使用指南
      • 1. 环境准备
      • 2. 实战举例
      • 3. 常见问题解决
    • 五、算法深度解析:揭秘加密背后的数学原理
      • 1. 凯撒密码的数学本质
      • 2. 异或运算的神奇特性
      • 3. Base64的编码奥秘
    • 六、总结与展望:安全编程的下一步
      • 1. 学习收获
      • 2. 安全性说明
      • 3. 进阶方向

在数字化时代,数据安全变得越来越重要。今天我们将用C++从零构建一个简易但功能完善的文件加密工具,支持凯撒密码异或加密Base64编码三种经典算法,兼容Dev C++ 5.11环境。

一、初识文件加密:为什么需要保护我们的文件?

想象一下,你有一份重要的文档,里面记录着你的日记、密码或者商业机密。如果这个文件被别人轻易打开,后果不堪设想。这时候,文件加密就像给你的文件上了一把锁,只有知道密码的人才能打开。

计算机安全和数据隐私是现代应用程序设计中至关重要的方面。为了确保数据的机密性和完整性,常常需要使用加密和解密算法。

在这里插入图片描述

1. 加密的基本概念

加密是将可读的明文转换为不可读的密文的过程,而解密则是相反的过程。就像:

  • 明文Hello World!
  • 密文Khoor Zruog!(凯撒加密,位移3)

2. 为什么选择这三种算法?

  • 凯撒密码:是已知最早的代替密码,通过对字母进行固定偏移量的移位操作来加密和解密消息,简单易懂,适合入门学习
  • 异或加密:基于异或运算的简单且常见的加密技术,简单性和高效性使得它在某些场景下很有用
  • Base64编码:用于将二进制数据转换成可打印的ASCII字符串,广泛应用于数据传输和存储领域

二、工具介绍:三大经典加密算法一网打尽

我们的加密工具支持三种不同的加密方式,每种都有其独特的特点和应用场景。

在这里插入图片描述

1. 凯撒密码(Caesar Cipher)

凯撒密码是一种最简单且最广为人知的加密技术,明文中的所有字母都在字母表上向后(或向前)按照一个固定数目进行偏移。

工作原理

  • 将字母表中的每个字母向右移动固定位数
  • 例如:位移3时,A→D, B→E, C→F
  • 到达字母表末尾时循环回到开头:X→A, Y→B, Z→C

2. 异或加密(XOR Encryption)

异或加密使用异或运算(XOR),它有一个神奇的特性:A XOR B XOR B = A,这意味着加密和解密可以使用同一个操作!

工作原理

  • 将文本中的每个字符与密钥字符进行异或运算
  • 密钥循环使用:如果密钥比文本短,就重复使用
  • 同样的密钥既能加密也能解密

3. Base64编码

Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,虽然不是真正意义上的加密,但可以将文件内容转换为看起来像乱码的字符串。

工作原理

  • 将3个8位字节转换为4个6位字节
  • 使用64个可打印字符表示数据
  • 输出结果可能包含=作为填充字符

4. 环境兼容性说明

Dev-C++ 5.11使用MingW64/TDM-GCC编译器,遵循C++11标准,兼容C++98标准。我们的代码严格按照C++98标准编写,确保在Dev-C++ 5.11环境下完美运行。主要兼容性特点:

  • 使用传统的stringvector等STL容器
  • 避免使用C++11及以后的新特性
  • 采用经典的for循环语法
  • 使用.c_str()进行字符串转换

三、核心代码实现:手把手教你构建加密工具

下面是完整的C++代码实现,兼容Dev C++ 5.11:

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstdlib>using namespace std;class FileEncryption {
private:// Base64编码表static const string base64_chars;// 判断字符是否为Base64字符static bool is_base64(unsigned char c) {return (isalnum(c) || (c == '+') || (c == '/'));}public:// 凯撒加密static string caesarEncrypt(const string& text, int shift) {string result = "";for (size_t i = 0; i < text.length(); i++) {char c = text[i];if (isalpha(c)) {char base = islower(c) ? 'a' : 'A';c = ((c - base + shift) % 26) + base;}result += c;}return result;}// 凯撒解密static string caesarDecrypt(const string& text, int shift) {return caesarEncrypt(text, 26 - shift);}// 异或加密/解密(异或运算是可逆的)static string xorEncrypt(const string& text, const string& key) {string result = "";for (size_t i = 0; i < text.length(); i++) {result += char(text[i] ^ key[i % key.length()]);}return result;}// Base64编码static string base64Encode(const string& text) {string ret;int i = 0;int j = 0;unsigned char char_array_3[3];unsigned char char_array_4[4];const char* bytes_to_encode = text.c_str();int in_len = text.length();while (in_len--) {char_array_3[i++] = *(bytes_to_encode++);if (i == 3) {char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);char_array_4[3] = char_array_3[2] & 0x3f;for(i = 0; (i <4) ; i++)ret += base64_chars[char_array_4[i]];i = 0;}}if (i) {for(j = i; j < 3; j++)char_array_3[j] = '\0';char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);char_array_4[3] = char_array_3[2] & 0x3f;for (j = 0; (j < i + 1); j++)ret += base64_chars[char_array_4[j]];while((i++ < 3))ret += '=';}return ret;}// Base64解码static string base64Decode(const string& encoded_string) {int in_len = encoded_string.size();int i = 0;int j = 0;int in = 0;unsigned char char_array_4[4], char_array_3[3];string ret;while (in_len-- && ( encoded_string[in] != '=') && is_base64(encoded_string[in])) {char_array_4[i++] = encoded_string[in]; in++;if (i ==4) {for (i = 0; i <4; i++)char_array_4[i] = base64_chars.find(char_array_4[i]);char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];for (i = 0; (i < 3); i++)ret += char_array_3[i];i = 0;}}if (i) {for (j = i; j <4; j++)char_array_4[j] = 0;for (j = 0; j <4; j++)char_array_4[j] = base64_chars.find(char_array_4[j]);char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];for (j = 0; (j < i - 1); j++) ret += char_array_3[j];}return ret;}// 读取文件内容static string readFile(const string& filename) {ifstream file(filename.c_str());if (!file.is_open()) {cout << "错误:无法打开文件 " << filename << endl;return "";}string content;string line;while (getline(file, line)) {content += line + "\n";}file.close();// 移除最后一个多余的换行符if (!content.empty() && content[content.length()-1] == '\n') {content.erase(content.length()-1);}return content;}// 写入文件static bool writeFile(const string& filename, const string& content) {ofstream file(filename.c_str());if (!file.is_open()) {cout << "错误:无法创建文件 " << filename << endl;return false;}file << content;file.close();return true;}
};// Base64字符表定义
const string FileEncryption::base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ""abcdefghijklmnopqrstuvwxyz""0123456789+/";// 显示菜单
void showMenu() {cout << "\n========== 文件加解密工具 ==========" << endl;cout << "1. 凯撒加密" << endl;cout << "2. 凯撒解密" << endl;cout << "3. 异或加密" << endl;cout << "4. 异或解密" << endl;cout << "5. Base64编码" << endl;cout << "6. Base64解码" << endl;cout << "7. 查看文件内容" << endl;cout << "0. 退出程序" << endl;cout << "===================================" << endl;cout << "请选择操作: ";
}int main() {int choice;string inputFile, outputFile, content, result;int shift;string key;cout << "欢迎使用简易文件加解密工具!" << endl;while (true) {showMenu();cin >> choice;switch (choice) {case 1: // 凯撒加密cout << "请输入要加密的文件名: ";cin >> inputFile;content = FileEncryption::readFile(inputFile);if (content.empty()) break;cout << "请输入位移值 (1-25): ";cin >> shift;shift = shift % 26;result = FileEncryption::caesarEncrypt(content, shift);cout << "请输入输出文件名: ";cin >> outputFile;if (FileEncryption::writeFile(outputFile, result)) {cout << "凯撒加密完成!已保存到 " << outputFile << endl;}break;case 2: // 凯撒解密cout << "请输入要解密的文件名: ";cin >> inputFile;content = FileEncryption::readFile(inputFile);if (content.empty()) break;cout << "请输入位移值 (1-25): ";cin >> shift;shift = shift % 26;result = FileEncryption::caesarDecrypt(content, shift);cout << "请输入输出文件名: ";cin >> outputFile;if (FileEncryption::writeFile(outputFile, result)) {cout << "凯撒解密完成!已保存到 " << outputFile << endl;}break;case 3: // 异或加密cout << "请输入要加密的文件名: ";cin >> inputFile;content = FileEncryption::readFile(inputFile);if (content.empty()) break;cout << "请输入密钥: ";cin >> key;result = FileEncryption::xorEncrypt(content, key);cout << "请输入输出文件名: ";cin >> outputFile;if (FileEncryption::writeFile(outputFile, result)) {cout << "异或加密完成!已保存到 " << outputFile << endl;cout << "注意:请记住密钥 \"" << key << "\",解密时需要使用相同密钥!" << endl;}break;case 4: // 异或解密cout << "请输入要解密的文件名: ";cin >> inputFile;content = FileEncryption::readFile(inputFile);if (content.empty()) break;cout << "请输入密钥: ";cin >> key;result = FileEncryption::xorEncrypt(content, key); // 异或解密与加密相同cout << "请输入输出文件名: ";cin >> outputFile;if (FileEncryption::writeFile(outputFile, result)) {cout << "异或解密完成!已保存到 " << outputFile << endl;}break;case 5: // Base64编码cout << "请输入要编码的文件名: ";cin >> inputFile;content = FileEncryption::readFile(inputFile);if (content.empty()) break;result = FileEncryption::base64Encode(content);cout << "请输入输出文件名: ";cin >> outputFile;if (FileEncryption::writeFile(outputFile, result)) {cout << "Base64编码完成!已保存到 " << outputFile << endl;}break;case 6: // Base64解码cout << "请输入要解码的文件名: ";cin >> inputFile;content = FileEncryption::readFile(inputFile);if (content.empty()) break;result = FileEncryption::base64Decode(content);cout << "请输入输出文件名: ";cin >> outputFile;if (FileEncryption::writeFile(outputFile, result)) {cout << "Base64解码完成!已保存到 " << outputFile << endl;}break;case 7: // 查看文件内容cout << "请输入要查看的文件名: ";cin >> inputFile;content = FileEncryption::readFile(inputFile);if (!content.empty()) {cout << "\n文件内容:" << endl;cout << "----------------------------------------" << endl;cout << content << endl;cout << "----------------------------------------" << endl;}break;case 0: // 退出cout << "感谢使用!再见!" << endl;return 0;default:cout << "无效选择,请重新输入!" << endl;break;}}return 0;
}

四、实战演练:从入门到精通的使用指南

1. 环境准备

  • 编译器:Dev C++ 5.11或其他支持C++98的编译器
  • 文件准备:创建一个测试文件test.txt,内容为:Hello World! This is a test file.

2. 实战举例

在这里插入图片描述

场景一:使用凯撒密码保护日记

1. 选择"1. 凯撒加密"
2. 输入文件名:diary.txt
3. 输入位移值:5
4. 输出文件:diary_encrypted.txt

先加密:

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
将之前的diary.txt删掉,之后,我们进行解密:

在这里插入图片描述

在这里插入图片描述

场景二:使用异或加密保护密码文件

1. 选择"3. 异或加密"  
2. 输入文件名:passwords.txt
3. 输入密钥:MySecretKey2025
4. 输出文件:passwords_encrypted.txt

先加密:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
同样地,将之前的passwords.txt删掉,我们进行解密:

在这里插入图片描述

可以看到已解密成功

在这里插入图片描述

场景三:使用Base64编码传输文件

1. 选择"5. Base64编码"
2. 输入文件名:document.txt  
3. 输出文件:document_base64.txt

先加密:

在这里插入图片描述
在这里插入图片描述

同样地,将之前的document.txt删掉,我们再进行解密:

在这里插入图片描述
在这里插入图片描述

3. 常见问题解决

问题1:文件读取失败

  • 解决方案:确保文件在程序同目录下,文件名输入正确

问题2:中文乱码

  • 解决方案:保存文件时使用UTF-8编码,或在代码中添加locale设置

问题3:异或解密失败

  • 解决方案:确保使用与加密时完全相同的密钥,区分大小写

五、算法深度解析:揭秘加密背后的数学原理

1. 凯撒密码的数学本质

凯撒密码的加密解密算法,就是两个公式:加密公式 f(a)=(a+k) mod 26,解密公式 f(a)=(a+26-k) mod 26

// 加密:字符向前移动k位
char encrypt = ((original - 'A' + shift) % 26) + 'A';// 解密:字符向后移动k位  
char decrypt = ((encrypted - 'A' + 26 - shift) % 26) + 'A';

模运算的妙用

  • % 操作确保结果始终在0-25范围内
  • 实现了字母表的"循环"特性
  • Z的下一个字母是A,形成闭环

2. 异或运算的神奇特性

异或运算有几个重要性质:

  • 交换律A ⊕ B = B ⊕ A
  • 结合律(A ⊕ B) ⊕ C = A ⊕ (B ⊕ C)
  • 自逆性A ⊕ A = 0A ⊕ 0 = A
  • 可逆性:如果C = A ⊕ B,那么A = C ⊕ B

这就是为什么异或加密和解密用同一个函数的原因!

3. Base64的编码奥秘

Base64要求把每三个8Bit的字节转换为四个6Bit的字节(3×8 = 4×6 = 24)

编码过程

  1. 将3个字节(24位)分组
  2. 重新组织为4个6位的组
  3. 每个6位数对应Base64字符表中的一个字符
  4. 不足的部分用=填充

六、总结与展望:安全编程的下一步

1. 学习收获

通过这个项目,我们掌握了:

  • C++基础应用:文件操作、字符串处理、类的设计
  • 加密算法原理:三种经典算法的工作机制
  • 实际编程技巧:错误处理、用户交互、代码组织

2. 安全性说明

⚠️ 重要提醒

  • 这是一个教学工具,不建议用于重要数据的加密
  • 凯撒密码的安全性非常低,容易受到破解,只有26个可能的密钥,可以在短时间内被暴力破解
  • 异或加密的安全性取决于密钥的复杂度
  • Base64只是编码,不是真正的加密

3. 进阶方向

如果你想继续深入学习加密技术,可以考虑:

  • 现代加密算法:AES、RSA、ECC等
  • 密码学库:OpenSSL、Crypto++等
  • 密码学理论:数论、椭圆曲线、量子密码学
  • 安全工程:密钥管理、数字签名、安全协议

总结:通过构建这个简易的文件加解密工具,我们不仅学会了C++编程技巧,更重要的是理解了信息安全的基本概念。虽然这些算法在现代标准下并不够安全,但它们是通往高级密码学的重要stepping stone。记住,真正的安全不仅在于算法的复杂性,更在于正确的使用方式和完善的安全策略

创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊)

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

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

相关文章

Qt/C++学习系列之Excel使用记录

Qt/C学习系列之Excel使用记录 前言The process was ended forcefully.解决方式断点查语句问题 总结 前言 在项目中解析条目达50多条&#xff0c;并且都需要将对应的结果进行显示。为了将结果显示的更加清晰&#xff0c;考虑采用QTableWidget进行表格设置&#xff0c;而在使用过…

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…

并发编程实战(生产者消费者模型)

在并发编程中使用生产者和消费者模式能够解决绝大多数的并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序整体处理数据的速度。 生产者和消费者模式&#xff1a; 在线程的世界中生产者就是产生数据的线程&#xff0c;而消费者则是消费数据的线程。在多线程开…

力扣hot100---152.乘积最大子数组

给你一个整数数组 nums &#xff0c;请你找出数组中乘积最大的非空连续子数组&#xff08;该子数组中至少包含一个数字&#xff09;&#xff0c;并返回该子数组所对应的乘积。 测试用例的答案是一个 32-位 整数。 示例 1: 输入: nums [2,3,-2,4] 输出:6解释: 子数组 [2,3] 有最…

什么是DevOps智能平台的核心功能?

在数字化转型的浪潮中&#xff0c;DevOps智能平台已成为企业提升研发效能、加速产品迭代的核心工具。然而&#xff0c;许多人对“DevOps智能平台”的理解仍停留在“自动化工具链”的表层概念。今天&#xff0c;我们从一个真实场景切入&#xff1a;假设你是某互联网公司的技术负…

柯尼卡美能达Konica Minolta bizhub 205i打印机信息

基本参数 产品类型&#xff1a;激光数码复合机颜色类型&#xff1a;黑白涵盖功能&#xff1a;复印、打印、扫描最大原稿尺寸&#xff1a;A3内存容量&#xff1a;256MB供纸容量&#xff1a;标配 350 页&#xff0c;最大 1350 页介质重量&#xff1a;标准纸盒 64-157g/㎡&#xf…

虚拟机与宿主机应用通信配置指南

1. 选择虚拟机网络模式 桥接模式 (Bridged) 客户机获得独立局域网IP&#xff0c;与宿主机同网段。 客户机可直接访问宿主机IP&#xff08;如 192.168.1.x&#xff09;。 Host-Only 模式 仅宿主机与客户机之间通信&#xff0c;宿主机通常有一个虚拟网卡&#xff08;如 192.16…

网络库libhv介绍

libhv是一个类似于libevent、libev、libuv的跨平台网络库&#xff0c;提供了更易用的接口和更丰富的协议&#xff0c;用来开发TCP/UDP/SSL/HTTP/WebSocket/MQTT 客户端/服务端。源码地址&#xff1a;https://github.com/ithewei/libhv&#xff0c;最新发布版本为v1.3.3&#xf…

施耐德特价型号伺服电机VIA0703D31A1022、常见故障

⚙️ ‌一、启动类故障‌ ‌电机无法启动‌ ‌可能原因‌&#xff1a;电源未接通、制动器未释放、接线错误或控制器故障。‌解决措施‌&#xff1a; 检查电源线路及断路器状态&#xff1b;验证制动器是否打开&#xff08;带制动器型号&#xff09;&#xff1b;核对电机与控制器…

【Redis从入门到精通实战文章汇总】

&#x1f4da;博客主页&#xff1a;代码探秘者 ✨专栏&#xff1a;文章正在持续更新ing… ✅C语言/C&#xff1a;C&#xff08;详细版&#xff09; 数据结构&#xff09; 十大排序算法 ✅Java基础&#xff1a;JavaSE基础 面向对象大合集 JavaSE进阶 Java版数据结构JDK新特性…

MCP 技术完全指南:微软开源项目助力 AI 开发标准化学习

引言 在人工智能快速发展的今天&#xff0c;如何让 AI 模型与客户端应用程序之间建立标准化的交互机制&#xff0c;已成为开发者们亟待解决的关键问题。微软近期开源的 mcp-for-beginners 项目&#xff0c;为我们提供了一个系统性学习 Model Context Protocol (MCP) 的绝佳机会…

SQL进阶之旅 Day 20:锁与并发控制技巧

【JDK21深度解密 Day 20】锁与并发控制技巧 文章简述 在高并发的数据库环境中&#xff0c;锁与并发控制是保障数据一致性和系统稳定性的核心机制。本文作为“SQL进阶之旅”系列的第20天&#xff0c;深入探讨SQL中的锁机制、事务隔离级别以及并发控制策略。文章从理论基础入手…

Qt(part 2)1、Qwindow(菜单栏,工具栏,状态栏),铆接部件,核心部件 ,2、添加资源文件 3、对话框

1、Qwindow tips&#xff1a;1&#xff0c;首先为什么创建出的对象基本都是指针形式&#xff0c;个人觉得是对象树的原因&#xff08;自动释放内存&#xff09;&#xff0c;指针来访问成员函数->的形式。2&#xff0c;菜单栏只能一个的&#xff0c;放窗口基本Set&#xff0c…

一款“短小精悍的”手机录屏软件

这个时代&#xff0c;手机自带录屏功能已经不是什么稀奇的事情了&#xff0c;但是手机自带的录屏功能不都是完美的&#xff0c;无法静音录屏、、不能修改画质、不能剪辑、不能自定义水印......emmm.....貌似除了录屏就什么都不会 今天分享的这款软件——ADV屏幕录制汉化版&…

力扣HOT100之二分查找:153. 寻找旋转排序数组中的最小值

这道题是上一道题&#xff1a;33. 搜索旋转排序数组的前置题&#xff0c;有点没看懂力扣为什么要这样安排题目顺序&#xff0c;应该把这道题按排在前面才对啊。。。这道题的思路已经在上一道题的思路中说过了&#xff0c;这里就直接复制粘贴上一篇博客中的内容了。 我们阅读完题…

libiec61850 mms协议异步模式

之前项目中使用到libiec61850库&#xff0c;都是服务端开发。这次新的需求要接收服务端的遥测数据&#xff0c;这就涉及到客户端开发了。 客户端开发没搞过啊&#xff0c;挑战不少&#xff0c;但是人不就是通过战胜困难才成长的嘛。通过查看libiec61850的客户端API发现&#xf…

【 知你所想 】基于ernie-x1-turbo推理模型实现趣味猜心游戏

&#x1f31f; 项目特点 &#x1f916; 智能AI&#xff1a;基于文心一言大模型&#xff0c;具有强大的推理能力&#x1f3af; 实时思考&#xff1a;展示AI的思考过程&#xff0c;让你了解AI是如何推理的&#x1f3ae; 互动性强&#xff1a;通过简单的"是/否"问答&…

Excel 模拟分析之单变量求解简单应用

正向求解 利用公式根据贷款总额、还款期限、贷款利率&#xff0c;求每月还款金额 反向求解 根据每月还款能力&#xff0c;求最大能承受贷款金额 参数&#xff1a; 目标单元格&#xff1a;求的值所在的单元格 目标值&#xff1a;想要达到的预期值 可变单元格&#xff1a;变…

关于easyexcel动态下拉选问题处理

前些日子突然碰到一个问题&#xff0c;说是客户的导入文件模版想支持部分导入内容的下拉选&#xff0c;于是我就找了easyexcel官网寻找解决方案&#xff0c;并没有找到合适的方案&#xff0c;没办法只能自己动手并分享出来&#xff0c;针对Java生成Excel下拉菜单时因选项过多导…

【Qt】之【Get√】【Bug】通过值捕获(或 const 引用捕获)传进 lambda,会默认复制成 const

通过值捕获&#xff08;或 const 引用捕获&#xff09;传进 lambda&#xff0c;会默认复制成 const。 背景 匿名函数外部定义 QSet<QString> nameSet,需要传入匿名函数使用修改 connect(dlg, ..., [nameSet](...) {nameSet.insert(name); // ❌ 这里其实是 const QSet…