迭代器作为参数传递时出现异常递增问题
解决sregex_iterator传递时的异常递增问题
嘿,我懂你碰到的麻烦了——用正则提取OBJ文件坐标时,明明确定每行有3个匹配项,可传递迭代器的时候总因为莫名其妙的递增导致结果不对对吧?这事儿主要跟sregex_iterator的特性有关,咱们一步步来解决:
核心问题:sregex_iterator是“用一次就往前走”的迭代器
sregex_iterator比较特殊,每次你解引用它(比如*it)或者调用++it,它都会自动跳到下一个匹配项。如果直接传递这个迭代器,不管是传值还是传引用,一不小心就会因为误操作让它跳过了你要的匹配项,尤其是在函数之间传递的时候,很容易搞混当前指向的位置。
最稳妥的解决方案:先把匹配结果存进容器再用
与其跟迭代器的递增特性较劲,不如先把所有匹配到的坐标值提取到一个容器(比如vector)里,之后不管是输出、存结构体还是传递给其他函数,都直接用容器里的元素,完全避免迭代器的坑。
给你写个示例代码:
#include <regex> #include <string> #include <vector> #include <iostream> #include <string> // 定义你的顶点结构体 struct Vertex { double x, y, z; }; int main() { std::string line = "v 12.3 -45 6.78"; // 模拟OBJ文件的顶点行 std::regex regCoord("-?\\d+\\.?\\d*"); std::sregex_iterator it(line.begin(), line.end(), regCoord); std::sregex_iterator endIter; // 默认构造的迭代器就是结束标志 // 把所有匹配结果捞进vector里 std::vector<std::string> coordStrs; while (it != endIter) { coordStrs.push_back(it->str()); ++it; } // 既然你确定有3个匹配项,直接用就行 if (coordStrs.size() == 3) { // 输出到控制台 std::cout << "X坐标:" << coordStrs[0] << "\nY坐标:" << coordStrs[1] << "\nZ坐标:" << coordStrs[2] << std::endl; // 存入结构体 Vertex vertex; vertex.x = std::stod(coordStrs[0]); vertex.y = std::stod(coordStrs[1]); vertex.z = std::stod(coordStrs[2]); } return 0; }
如果一定要传递迭代器,得注意这些点
要是你非得直接传递迭代器,那得小心这两个坑:
- 别传引用:如果把迭代器以引用方式传给函数,函数里的
++it会直接改变外部迭代器的位置,等函数返回后,外部的迭代器可能已经指向结束位置了,再用就会出问题。 - 明确控制递增次数:如果在函数里处理迭代器,要精准只递增两次(因为一开始指向第一个匹配,递增两次后到第三个),别多增也别少增。比如:
void printCoords(std::sregex_iterator it) { // 第一个匹配 std::cout << "第一个值:" << it->str() << std::endl; ++it; // 第二个匹配 std::cout << "第二个值:" << it->str() << std::endl; ++it; // 第三个匹配 std::cout << "第三个值:" << it->str() << std::endl; } // 调用的时候传迭代器的拷贝,不会影响外部的迭代器 std::sregex_iterator it(line.begin(), line.end(), regCoord); printCoords(it);
顺带提个正则小优化
你的正则"-?\\d+\\.?\\d*"其实能匹配到像123.这种带小数点但后面没数字的情况,如果OBJ文件里的坐标都是规范格式,你可以把正则改成"-?\\d+(?:\\.\\d+)?",这样只会匹配整数(比如-45)或者完整的小数(比如12.3),避免匹配到不规范的格式。
总结
还是推荐先把匹配结果存进容器,这种方式代码更清晰,也完全规避了迭代器递增的异常问题,特别适合你这种确定每行有固定数量匹配项的场景。
内容的提问来源于stack exchange,提问作者Ярослав Живрин
相关产品推荐
相关产品推荐

