c++ - C++:尝试用等效的 STL 算法消除原始循环
问题描述
我正在尝试使一些 C++ 代码现代化,遵守核心准则并发布 ++11 建议。我在这里提出的具体指导方针是使用<algorithm>
设施来代替原始循环,在整个序列中应用静态操作,目的是生成一个新序列。
第一个示例说明了成功(正如我在此上下文中定义的那样)。进来的两个输入向量std::byte
,一个出来,代表每个输入向量的成对按位异或,输入向量保持不变。这个问题的精神功能是std::transform.
vector<byte> XORSmash(const vector<byte>& first, const vector<byte>& second)
{
if (first.size() != second.size())
throw std::invalid_argument("XORSMASH: input vectors were not of equal length\n");
vector<byte> convolution; convolution.reserve(first.size());
transform(first.cbegin(), first.cend(), second.cbegin(), back_inserter(convolution),
[](const byte byte1, const byte byte2) {return byte1 ^ byte2;} );
return convolution;
}
但是,还有另一个功能,我在设计一个非循环解决方案时遇到了麻烦,该解决方案并不比循环解决方案差。这个函数接受一个string
HexChars(每个char最终传达4位值),并生成一个vector<byte>
,每个元素包含两个HexChars的内容,一个在高4位,一个在低位。该CharToHexByte
函数的确切作用无关紧要(如果有必要,我将包括在内),只是它需要一个兼容的十六进制字符,并返回一个std::byte
,以及十六进制字符的数值,即 0-15,仅加载 4 位。问题是输入字符串有成对的十六进制字符(每个字符都是半字节值),每个字符都统一为一个十六进制字节。据我所知,我不能使用std::transform
,因为输入迭代器必须跳 2 (2 * sizeof(char)//aka container_const_iterator += 2 in this case
) 每次迭代,提取输入字符串中的下一对字符。
TLDR:是否有一种算法方法来实现以下功能而没有暴露的for
循环,这并不比下面的解决方案更昂贵/更冗长?
vector<byte> UnifyHexNibbles(const string& hexStr)
{
if (hexStr.size() % 2)
throw std::invalid_argument("UnfyHxNbl: Input String Indivisible by 8bits. Pad if applicable.\n");
vector<byte> hexBytes; hexBytes.reserve(hexStr.size() >> 1);
//can I be eliminated elegantly?
for (size_t left(0), right(1); right < hexStr.size(); left += 2, right += 2)
hexBytes.push_back( CharToHexByte(hexStr[left]) << 4 | CharToHexByte(hexStr[right]) );
return hexBytes;
}
解决方案
使用range-v3,它将是
std::vector<std::byte>
UnifyHexNibbles(const std::string& hexStr)
{
if (hexStr.size() % 2)
throw std::invalid_argument("size indivisible by 2.");
return hexStr
| ranges::view::chunk(2)
| ranges::view::transform([](const auto& r)
{
return std::byte(CharToHexByte(r[0]) << 4 | CharToHexByte(r[1]));
});
}
推荐阅读
- oauth - 如何使用 twitter 的空手道设置 oauth 1.0 身份验证?
- python - Plotly:如何使用 plotly.graph_objects 制作由变量着色的折线图?
- linux - 当不存在文件时,Linux 中的 for 循环将模式视为文件名
- javascript - 基于路由路径的深层嵌套路由和不同组件渲染
- reporting-services - 为什么 RDLC 本地报表图表与 RDL(SSRS) 有不同的图形?
- c - 是否有类似 switch 的关键字可以接受字符串(char *)而不仅仅是 char?
- junit - 为什么在 JUnit 或 Android 测试用例中使用名称“断言”?
- git - 使用自定义 ssh 密钥从 gitlab 克隆存储库?
- ckeditor - CKEditor 4.13 - 样式(div.xyz)来自哪个核心或插件?
- rally - 具有深度导出的 Rally 自定义列表问题(错误)