如何用符合C++核心准则的代码替换C风格的字符串解析
How can I replace the C-style string parsing with C++ core guideline-compliant code?
以这两个代码片段为例:
//...
file_string = strstr(file_string, "nv ");
while (file_string = strstr(file_string, "v ")) {
vec::vec3<float> buffer = { 0.0f };
file_string += strlen("v ");
file_string = std::from_chars(file_string, file_string_end, buffer.x).ptr;
file_string++;
file_string = std::from_chars(file_string, file_string_end, buffer.y).ptr;
file_string++;
file_string = std::from_chars(file_string, file_string_end, buffer.z).ptr;
file_string++;
vcoords.push_back(std::move(buffer));
}
//...
//...
while (file_string = strstr(file_string, "v ")) {
size++;
file_string++;
}
vcoords.reserve(size);
//...
对于这种类型的数据
(...)
v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 -1.000000
(...)
他们工作得很快。它们还生成警告,例如:
C26481: Don't use pointer arithmetic.
C26486: Don't pass a pointer that may be invalid to a function. Parameter 0 'file_string' in call to 'strstr' may be invalid (lifetime.3).
如何将strstr/pointer算术组合替换为能够以相对较快的速度完成任务而不会生成此类警告的组合?我试着研究与std::string
到float
转换相关的类似问题,但他们要么使用了非常慢的std::stringstream
,要么假设有问题的字符串只包含一个值。
在启用核心指导原则检查器后编辑更改
我尝试过使用std::from_chars
。有趣的事实:它还不能在gcc或clang上为浮点值工作!那个在功能成熟之前可能不需要使用它。
关闭指南检查器的事情:
gsl::at
是指针运算的欺骗代码。没有警告- 寿命检查器有点笨。它不知道由
string_view
包装的字符串文字仍然有无限的生存期,但如果您使用字符串视图文字("sv(,它不会进行标记 - 仍使用
string::find
进行搜索,然后将位置添加到string::data()
- 我以前建议索引而不是指针算术,但分析也不喜欢这样
using namespace std::literals;
const std::string file_string = "n"
"v 1.000000 1.000000 -1.000000n"
"v 1.000000 -1.000000 -1.000000n"
"v 1.000000 1.000000 1.000000n";
const auto tag = "v "sv;
const char* file_string_end = &gsl::at(file_string, file_string.size());
std::vector<vec::vec3<float>> vcoords;
std::string::size_type pos = 0;
while ((pos = file_string.find(tag, pos)) != std::string::npos) {
vec::vec3<float> buffer = { 0.0f };
auto [x_ptr, x_ec] = std::from_chars(
&gsl::at(file_string, pos + tag.size()),
file_string_end,
buffer.x);
if (x_ec != std::errc()) {
throw std::runtime_error("bad x");
}
std::string_view x_view(x_ptr);
auto [y_ptr, y_ec] = std::from_chars(
&gsl::at(x_view, 1),
file_string_end,
buffer.y);
if (y_ec != std::errc()) {
throw std::runtime_error("bad y");
}
std::string_view y_view(y_ptr);
auto [z_ptr, z_ec] = std::from_chars(
&gsl::at(y_view, 1),
file_string_end,
buffer.z);
if (z_ec != std::errc()) {
throw std::runtime_error("bad z");
}
vcoords.push_back(buffer);
}
https://godbolt.org/z/F9j7FA
相关文章:
- 模板参数替换失败,并且未完成隐式转换
- Qt VTK交互风格的信号到小部件
- 如何用转义符替换字符串中的所有特殊字符
- 我可以使用条件运算符初始化C风格的字符串文字吗
- Visual Studio 2019:插入多个C++风格的单行注释
- 如何在本地机器上运行c++和javascript客户端代码(hackerbank风格)
- 为什么除非添加括号,否则构造函数上的模板替换会失败?
- 在一个读写器队列中,我可以用volatile替换原子吗
- 用符号版本替换对函数的所有调用
- 如何通过替换顺序代码的while循环来添加OpenMP for循环
- 替换基于地图的所有引用
- 按平均值替换数组中的元素
- 我可以在这里替换什么,因为我不能在 C# 中使用隐式变量的 lambda 函数?
- 如何将字节数组元素替换为修改的十六进制 ASCII 符号?
- 初始化 std::vector 替换为单大括号而不是双大括号
- 删除/替换C++字符串中的多字符 (ÿû)
- 如何用符合C++核心准则的代码替换C风格的字符串解析
- 用现代C++STL数据结构替换旧的C风格数组
- 是否有一种替换C风格的Bool数组的标准方法
- c++中Python风格的字符串替换