C++常见通用自写算法集合

发布时间:2026/10/22 12:51:16

C++常见通用自写算法集合 目录1.字符串大小写转换2.容器内容去重3.求文件的sha值3.1.在vcpkg中安装openssl和asio库3.2.同步读取文件求sha值3.3.优化:用内存映射方式求sha值3.4.优化:异步读取文件求sha值3.5.几种方法性能比较4.求容器的最大最小值5.求容器内元素的平均值1.字符串大小写转换CommFunc.h#pragma once #include string namespace util { std::string to_upper(std::string_view src); std::string to_upper(const std::string src); std::string to_upper(std::string src); std::string to_lower(std::string_view src); std::string to_lower(const std::string src); std::string to_lower(std::string src); } // namespace utilCommFunc.cpp#include CommFunc.h #include algorithm #include cctype #include iterator namespace util { templatetypename Container, typename Func int(int) std::string _transform(Container src, Func func) { std::string dst; dst.reserve(src.size()); std::transform(src.cbegin(), src.cend(), std::back_inserter(dst), [toUpper std::move(func)](unsigned char c) - char { return static_castchar(toUpper(static_castint(c))); }); return dst; } std::string to_upper(std::string_view src) { #if 0 std::string dst; dst.reserve(src.size()); std::transform(src.cbegin(), src.cend(), std::back_inserter(dst), [](unsigned char c) - char { return static_castchar(std::toupper(static_castint(c))); }); return dst; #else return _transform(src, std::toupper); #endif } std::string to_upper(const std::string src) { #if 0 std::string dst; dst.reserve(src.size()); std::transform(src.cbegin(), src.cend(), std::back_inserter(dst), [](unsigned char c) - char { return static_castchar(std::toupper(static_castint(c))); }); return dst; #else return _transform(src, std::toupper); #endif } std::string to_upper(std::string src) { std::transform(src.begin(), src.end(), src.begin(), [](unsigned char c) - char { return static_castchar(std::toupper(static_castint(c))); }); return src; } std::string to_lower(std::string_view src) { #if 0 std::string dst; dst.reserve(src.size()); std::transform(src.cbegin(), src.cend(), std::back_inserter(dst), [](unsigned char c) - char { return static_castchar(std::tolower(static_castint(c))); }); return dst; #else return _transform(src, std::tolower); #endif } std::string to_lower(const std::string src) { #if 0 std::string dst; dst.reserve(src.size()); std::transform(src.cbegin(), src.cend(), std::back_inserter(dst), [](unsigned char c) - char { return static_castchar(std::tolower(static_castint(c))); }); return dst; #else return _transform(src, std::tolower); #endif } std::string to_lower(std::string src) { std::transform(src.begin(), src.end(), src.begin(), [](unsigned char c) - char { return static_castchar(std::tolower(static_castint(c))); }); return src; } } // namespace util优点不需要手动 resize不会因为大小不匹配出现内存 bug推荐。如果还是报错改用全局 ::tolower部分旧编译器 / 库的坑std::transform(src.cbegin(), src.cend(), std::back_inserter(dst), [](unsigned char c) - char { return static_castchar(::tolower(static_castint(c))); });区别std::tolower是 C 版本::tolower是 C 标准库全局符号有些平台头文件混乱会找不到std::tolower。2.容器内容去重C反射之检测struct或class是否实现指定函数//容器内容去重 templatetypename Container, typename Compare std::less void deduplicateContainer(Container container, Compare comp Compare());详细实现#pragma once #include algorithm #include iterator #include type_traits namespace util { #define HAS_NON_STATIC_AND_NON_CONST_MEMBER_EX1(R, member) \ templatetypename T struct has_non_static_member_ex1_##member{ \ private:\ templatetypename Y, Y y \ class Helper; \ templatetypename U T \ constexpr static bool has##member(...) {\ return false;\ }\ templatetypename U T\ constexpr static bool has##member(HelperR (U::*)(), U::member*) {\ return true;\ }\ public:\ static const bool value has##memberT(nullptr);\ }; HAS_NON_STATIC_AND_NON_CONST_MEMBER_EX1(void, sort) // 判断容器是否可以使用 std::sort templatetypename Container constexpr bool can_use_std_sort std::is_base_of_v std::random_access_iterator_tag, typename std::iterator_traitstypename Container::iterator::iterator_category ; //容器内容去重 templatetypename Container, typename Compare void deduplicateContainer(Container container, Compare comp) { if constexpr (can_use_std_sortContainer) { std::sort(container.begin(), container.end(), comp); auto it std::unique(container.begin(), container.end()); container.erase(it, container.end()); } else if constexpr (has_non_static_member_ex1_sortContainer::value){ container.sort(comp); auto it std::unique(container.begin(), container.end()); container.erase(it, container.end()); } else { static_assert(false, Container not support sort!!!); } } } // namespace util3.求文件的sha值3.1.在vcpkg中安装openssl和asio库//安装asio和openssl vcpkg install asio openssl:x64-windows //在cmake引用 cmake_minimum_required(VERSION 3.16) project(file_hash) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(asio CONFIG REQUIRED) find_package(OpenSSL REQUIRED) add_executable(file_hash main.cpp) target_link_libraries(file_hash PRIVATE asio::asio OpenSSL::Crypto)3.2.同步读取文件求sha值std::string calc_sha256_sync(const std::string path) { std::ifstream f(path, std::ios::binary); if (!f) return ; SHA256_CTX ctx; SHA256_Init(ctx); const size_t BUF_SIZE 2*1024 * 1024; std::vectorchar buf(BUF_SIZE); while (true) { f.read(buf.data(), buf.size()); auto read_len f.gcount(); if (read_len 0) { SHA256_Update(ctx, buf.data(), read_len); } if (!f) break; } unsigned char h[SHA256_DIGEST_LENGTH]; SHA256_Final(h, ctx); char hexbuf[SHA256_DIGEST_LENGTH * 2 1]{}; for (int i 0;i SHA256_DIGEST_LENGTH;i) sprintf(hexbuf i * 2, %02x, h[i]); return std::string(hexbuf); }3.3.优化:用内存映射方式求sha值#pragma once #include windows.h #include openssl/evp.h #include string #include iostream namespace { constexpr char hex_lut2[] 0123456789abcdef; } // Windows原生内存映射计算SHA256 std::string calc_sha256_mmap_win(const std::string file_path) { HANDLE hFile CreateFileA( file_path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, // 顺序访问提示内核预读优化 nullptr ); if (hFile INVALID_HANDLE_VALUE) { std::cerr CreateFile failed\n; return {}; } LARGE_INTEGER file_size{}; if (!GetFileSizeEx(hFile, file_size)) { CloseHandle(hFile); return {}; } HANDLE hMap CreateFileMappingA(hFile, nullptr, PAGE_READONLY, 0, 0, nullptr); if (hMap nullptr) { CloseHandle(hFile); return {}; } // 映射整个文件到内存 const char* p_data static_castconst char*(MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)); if (p_data nullptr) { CloseHandle(hMap); CloseHandle(hFile); return {}; } // 哈希计算 EVP_MD_CTX* md_ctx EVP_MD_CTX_new(); EVP_DigestInit_ex(md_ctx, EVP_sha256(), nullptr); EVP_DigestUpdate(md_ctx, p_data, static_castsize_t(file_size.QuadPart)); unsigned char hash_bin[EVP_MAX_MD_SIZE]; unsigned int hash_len 0; EVP_DigestFinal_ex(md_ctx, hash_bin, hash_len); EVP_MD_CTX_free(md_ctx); // 转hex字符串 std::string hash_str; hash_str.resize(hash_len * 2); for (unsigned int i 0; i hash_len; i) { hash_str[i * 2] hex_lut[hash_bin[i] 4]; hash_str[i * 2 1] hex_lut[hash_bin[i] 0x0F]; } // 资源释放必须成对 UnmapViewOfFile(p_data); CloseHandle(hMap); CloseHandle(hFile); return hash_str; }3.4.优化:异步读取文件求sha值#include asio.hpp #include iostream #include vector #include functional #include fstream #include openssl/sha.h namespace { // 编译期十六进制查表比 sprintf 快 3~5 倍 constexpr char hex_lut[] 0123456789abcdef; // 缓冲区大小2MB 大缓冲减少系统调用次数可按场景调整为 256KB/1MB constexpr size_t BUF_SIZE 2 * 1024 * 1024; } std::string asyn_read_file_optimized(const std::string path) { try { asio::io_context io_context; // 优化1改用 stream_file 顺序流读取 // 比 random_access_file 更适合连续读取系统自动预读、无需维护偏移、调度开销更低 asio::stream_file file(io_context, path, asio::stream_file::read_only); SHA256_CTX sha_ctx; SHA256_Init(sha_ctx); std::string hash_result; // 优化2双缓冲流水线核心性能优化 // 重叠「磁盘IO」和「哈希计算」总耗时 max(IO耗时, 计算耗时)而非两者相加 std::vectorchar buf_a(BUF_SIZE); std::vectorchar buf_b(BUF_SIZE); bool use_buf_a true; // 标记当前用于IO的缓冲区 std::functionvoid() read_loop; read_loop []() { // 选择当前IO缓冲区 char* io_buf use_buf_a ? buf_a.data() : buf_b.data(); size_t io_buf_len use_buf_a ? buf_a.size() : buf_b.size(); file.async_read_some(asio::buffer(io_buf, io_buf_len), [, read_loop, io_buf](const asio::error_code ec, size_t bytes_read) { if (ec) { if (ec asio::error::eof) { // 读取结束生成最终哈希 unsigned char hash_bin[SHA256_DIGEST_LENGTH]; SHA256_Final(hash_bin, sha_ctx); //优化4查表法十六进制转换零格式解析开销 hash_result.resize(SHA256_DIGEST_LENGTH * 2); for (int i 0; i SHA256_DIGEST_LENGTH; i) { hash_result[i * 2] hex_lut[hash_bin[i] 4]; hash_result[i * 2 1] hex_lut[hash_bin[i] 0x0F]; } } else { std::cerr read error: ec.message() \n; } return; } // 流水线核心先切换缓冲区、发起下一次IO让磁盘先跑 use_buf_a !use_buf_a; read_loop(); // 异步发起下一块读取内核后台执行立即返回 // 同时计算当前块哈希与「下一块的IO」完全并行 if (bytes_read 0) { SHA256_Update(sha_ctx, io_buf, bytes_read); } }); }; read_loop(); io_context.run(); return hash_result; } catch (const std::exception e) { std::cerr exception: e.what() \n; return {}; } }双缓冲流水线大缓冲区2MB减少系统调用次数降低内核态切换开销。原理原代码是串行流程发起IO → 等待完成 → 计算哈希 → 发起下一次IOIO 和计算完全串行。优化后当前块读完后立刻发起下一块的异步读再回头计算当前块的哈希。磁盘 IO 和 CPU 计算完全重叠总耗时从「IO 总时间 计算总时间」缩短为max(IO总时间, 计算总时间)。收益大文件场景下SSD 环境提升 30%~50%高速存储环境下最高提升近 1 倍。3.5.几种方法性能比较文件 Hash 计算工具Windows用来校验你前面 C 代码的 SHA256 结果Windows 系统自带无需安装优先用和你的 C 代码做比对certutilCMD / PowerShell 都支持# SHA256和你代码一致推荐 certutil -hashfile D:\test.dat SHA256 # MD5 certutil -hashfile D:\test.dat MD5 # SHA1 certutil -hashfile D:\test.dat SHA1支持MD2 MD4 MD5 SHA1 SHA256 SHA384 SHA512测试结果4.求容器的最大最小值/// 通用求容器最大值 templatetypename Container auto container_max(const Container c) { if (c.empty()) throw std::runtime_error(container is empty!); return *std::max_element(c.cbegin(), c.cend()); } /// 通用求容器最小值 templatetypename Container auto container_min(const Container c) { if (c.empty()) throw std::runtime_error(container is empty!); return *std::min_element(c.cbegin(), c.cend()); }5.求容器内元素的平均值// 通用模板支持任意可迭代序列 算术类型元素约束 templatetypename Container auto average(Container cont) - std::enable_if_t std::is_arithmetic_v typename std::iterator_traitsdecltype(std::begin(cont))::value_type, double { // 提取元素真实类型 using ValueType typename std::iterator_traitsdecltype(std::begin(cont))::value_type; // 空容器安全处理避免除以0 const auto size std::size(cont); if (size 0) { return 0.0; } // 累加所有元素的绝对值初始值0.0保证浮点精度 double sumAbs std::accumulate( std::cbegin(cont), std::cend(cont), 0.0, [](double accum, ValueType val) { return accum val; } ); return sumAbs / static_castdouble(size); } // 新增重载专门支持花括号初始化列表 {a,b,c,...} templatetypename T std::enable_if_tstd::is_arithmetic_vT, double average(std::initializer_listT list) { // 直接复用通用版本的计算逻辑代码不重复 return average(list); }调用示例std::vectorint vecInts {1, 2, 100, 333, 444, -1}; auto sumOfInt average(vecInts); std::vectordouble vecDoubles { 1, 2, 100, 333, 444, 2}; auto sumOfDouble average(vecDoubles); int a[] {11, 33,23333, 435, 2211212, 3333, 5555,6666,432,111,233,3,3,33,34 }; auto sumOfInt1 average(a); // 3. std::array 固定数组 std::arrayint, 4 arrayValue { -10, 20, -30, 40 }; std::cout array均值: average(arrayValue) \n; auto sumOfInt2 average({11,22,33,44,56,777,88,99});后续待完。。。
延伸阅读

更多相关文章

2026/10/22 13:56:40

隔离内网MongoDB离线部署:从环境核查到安全认证的完整实践

这周刚在隔离内网里完成了一套MongoDB的离线部署,趁着手边的记录还热乎,把整个流程、踩过的坑和排查思路完整写下来。离线部署mongodb这件事表面看很简单——把安装包用U盘拷进去、解压、启动,但真正在隔离网段里动手才发现,依赖库…

2026/10/22 13:56:40

Keil HEX自动重命名:版本号+时间戳一键生成

简介:本资源是一款面向单片机开发者的Keil编译辅助工具,专为解决HEX文件缺乏版本标识与编译时间戳导致的固件管理混乱问题而设计。适用于嵌入式初学者及项目中需严格管控固件迭代的工程师,尤其在多版本并行调试、量产前固件归档等场景下价值突…

2026/10/22 13:56:40

用QwenImageEdit2512训练吉卜力风格LoRA:从环境搭建到踩坑实录

上个月有位朋友抱着一堆手绘动画截图来找我,说想把普通照片都处理成那种暖色调、大面积色块、天空像水彩晕染一样的动画风格。我给他的建议是:与其一遍遍调现成滤镜,不如直接拿QwenImageEdit2512这套开源图像编辑模型当基底,在它上…

2026/10/22 13:56:40

vLLM迁移昇腾NPU完全指南:从环境搭建到性能优化

把 vLLM 推理服务从 CUDA 环境迁移到昇腾 NPU 机器上,最开始的体验通常不会太友好。我自己的经历是:GPU 上稳定跑了几周的模型,到昇腾上第一天就段错误,第二天跑出 NaN,第三天吞吐低到让人怀疑拿到了假卡。后来一步步把…

2026/10/22 13:56:40

企业级AI Agent落地指南:从Demo到生产的四大死因与实操解法

1. 先搞清楚一个问题:你的项目其实不是在“做 Demo”,是在“躲验收”这几年我混迹在各类企业的智能体项目评审现场,有个很扎心的共识:十个 Agent 项目里,至少有七个走完 POC 就没了下文。有的团队烧了几个月算力&#…

2026/10/22 13:51:39

Redis分布式锁高并发实战:锁过期、误删与看门狗

1. 为什么"能用"的分布式锁,一到高并发就出事 先说个我在实际项目中反复看到的场景:系统刚上线时并发量不大,用 Redis 做锁,大家写 setnx 加锁、 del 解锁,跑得挺顺。等某个大促或活动流量一上来&#x…

2026/10/22 11:29:28

金融AI落地指南:从调研报告到技术选型与工程实践

简介:这份PDF报告聚焦2025年金融服务业中国AI现状与趋势,面向金融科技从业者、AI战略规划人员及关注行业数字化转型的研究者,帮助读者把握生成式AI在银行、支付、交易等场景中的落地路径与投资方向。资源包内含1个PDF文件,大小约1…

2026/10/22 0:01:49

电商智能运营体系从0到1:架构设计、落地步骤与避坑指南

前两年我们团队接了一个电商平台的运营中台项目,目标很直白:把过去靠运营拍脑袋做的选品、定价、发券、推活动这些事,逐步用数据算法和自动化流程代替。项目名字内部就叫“电商智能运营体系”。最近有不少朋友问我当时是怎么设计的、踩过哪些…

2026/10/22 0:01:49

若依框架AI代码生成不稳定?用Agent Skill三层结构+五步法搞定

最近一段时间,我一直想把后台管理系统里那些机械重复的增删改查代码交给AI去写。框架用的是若依,按理说这类业务代码模式非常固定,应该是AI最擅长的事情。可真试下来却不是那么回事——你让AI生成一个用户管理模块,它给出的Contro…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑