如何简化查找string_view中首个CLI选项的C++函数实现?
用C++标准算法简化
check_cli_option实现 你的需求逻辑可以拆分为前缀优先匹配和子串首次出现匹配两步,用C++标准算法分别实现这两个逻辑,既能避免手动循环的冗余,也不会出现合并循环后代码膨胀的问题。
第一步:前缀匹配
用std::find_if遍历选项数组,判断每个选项是否是目标cli_option的前缀。C++20及以上可以直接用std::string_view::starts_with,旧标准可以手动实现前缀判断:
#include <algorithm> #include <string_view> template <typename Iter> Iter check_cli_option(std::string_view cli_option, Iter first, Iter last) { // 优先匹配前缀 auto prefix_match = std::find_if(first, last, [&cli_option](const auto& opt) { return cli_option.starts_with(opt); }); if (prefix_match != last) { return prefix_match; } // 子串匹配逻辑见下文 }
第二步:子串首次出现匹配
这一步需要在数组中找到在cli_option里出现位置最早的子串选项。用std::min_element自定义比较规则:优先选择存在的选项,都存在则选出现位置更小的。
完整实现代码:
#include <algorithm> #include <string_view> #include <cstddef> template <typename Iter> Iter check_cli_option(std::string_view cli_option, Iter first, Iter last) { // 1. 前缀匹配优先 auto prefix_match = std::find_if(first, last, [&cli_option](const auto& opt) { return cli_option.starts_with(opt); }); if (prefix_match != last) { return prefix_match; } // 2. 查找首次出现的子串选项 auto earliest_substr = std::min_element(first, last, [&cli_option](const auto& a, const auto& b) { auto pos_a = cli_option.find(a); auto pos_b = cli_option.find(b); // 规则:存在的选项优先级高于不存在的;都存在则位置小的优先 if (pos_a == std::string_view::npos) return false; if (pos_b == std::string_view::npos) return true; return pos_a < pos_b; }); // 若所有选项都不是子串,返回last return (cli_option.find(*earliest_substr) != std::string_view::npos) ? earliest_substr : last; }
补充说明
- 你判断
std::find_first_of不适用是正确的:它的逻辑是找目标序列中任意元素出现在待查序列的情况,和你的需求(待查序列包含数组元素,还要区分前缀/子串优先级)完全不符。 - 旧标准兼容:如果无法使用C++20的
starts_with,可以手动实现前缀判断函数替换:auto is_prefix = [](std::string_view str, std::string_view prefix) { return str.size() >= prefix.size() && str.substr(0, prefix.size()) == prefix; };
内容的提问来源于stack exchange,提问作者digito_evo
相关产品推荐
相关产品推荐

