Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/drupal/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在清除循环中的向量时,如何避免超出范围的异常?_C++_String_Vector_While Loop_Erase - Fatal编程技术网

C++ 在清除循环中的向量时,如何避免超出范围的异常?

C++ 在清除循环中的向量时,如何避免超出范围的异常?,c++,string,vector,while-loop,erase,C++,String,Vector,While Loop,Erase,我为冗长的解释道歉 我正在研究一个C++应用程序,它将两个文件加载到两个2D字符串向量中,重新排列这些向量,再生成另一个2D字符串向量,并将它们全部输出到报表中。这两个向量的第一个元素是一个代码,用于标识项目的所有者和向量中的项目。我在启动时将所有者的标识传递给程序,并通过嵌套while循环中的两个向量进行循环,以找到具有匹配的第一个元素的向量。当我这样做时,我用前两个向量的分量构建第三个向量,然后我需要捕获任何不匹配的向量 当两个原始数组匹配时,我使用语法“vector.erase(vecto

我为冗长的解释道歉

我正在研究一个C++应用程序,它将两个文件加载到两个2D字符串向量中,重新排列这些向量,再生成另一个2D字符串向量,并将它们全部输出到报表中。这两个向量的第一个元素是一个代码,用于标识项目的所有者和向量中的项目。我在启动时将所有者的标识传递给程序,并通过嵌套while循环中的两个向量进行循环,以找到具有匹配的第一个元素的向量。当我这样做时,我用前两个向量的分量构建第三个向量,然后我需要捕获任何不匹配的向量

当两个原始数组匹配时,我使用语法“vector.erase(vector.begin()+I)”从中删除元素。循环完成后,我得到了新的第三个向量,剩下的两个向量只有元素,不匹配,这就是我需要的。当我尝试文件中的不同所有者时(程序一次只接受一个所有者),这工作正常。然后我尝试了一个产生超出范围错误的方法

我不知道如何在不抛出错误的情况下在循环内部执行擦除(似乎swap和pop或eraseremove都不是可行的解决方案)。在构建了第三个向量之后,我用两个额外的嵌套while循环解决了程序的问题

我想知道如何使擦除方法在这里工作(因为它似乎是一个更简单的解决方案),或者至少如何检查超出范围的错误(并避免它)。对于这个特定的所有者,有很多“行”;所以调试是乏味的。在放弃并继续使用嵌套的while解决方案之前,我确定第二次擦除引发了错误。我怎样才能做到这一点,或者说我在事后的努力是我所能做到的最好的吗?代码如下:

i = 0;
while (i < AIvector.size())
{
CHECK:
    j = 0;
    while (j < TRvector.size())
    {
        if (AIvector[i][0] == TRvector[j][0])
        {
            linevector.clear();
            // Add the necessary data from both vectors to Combo_outputvector 
            for (x = 0; x < AIvector[i].size(); x++)
            {
                linevector.push_back(AIvector[i][x]);  // add AI info
            }
            for (x = 3; x < TRvector[j].size(); x++) // Don't need the the first three elements; so start with x=3.
            {
                linevector.push_back(TRvector[j][x]); // add TR info 
            }
            Combo_outputvector.push_back(linevector); // build the combo vector

            // then erase these two current rows/elements from their respective vectors, this revises the AI and TR vectors 
            AIvector.erase(AIvector.begin() + i);
            TRvector.erase(TRvector.begin() + j);
            goto CHECK;  // jump from here because the erase will have changed the two increments
        }
        j++;
    }
    i++;
}
i=0;
而(i
如前所述,您的
转到
跳到了错误的位置。只要将它移出第一个
循环,而
循环就可以解决您的问题。但我们能做得更好吗

可以使用
std::remove
std::erase
干净地从向量中删除对象,这样移动对象就比较便宜,而
vector
string
都是。然而,经过一番思考,我认为这并不是最好的解决方案,因为您需要一个函数,它不仅可以检查两个容器中是否存在某一行,而且不容易用erase-remove习惯用法来表示

保留当前结构后,我们可以对循环条件使用迭代器。我们可以从中获得很多好处,因为
std::vector::erase
将迭代器返回到被删除元素之后的下一个有效元素。更不用说它需要一个迭代器。有条件地擦除向量中的元素变得非常简单

auto it = vec.begin()
while (it != vec.end()) {
    if (...) 
        it = vec.erase(it);
    else
        ++it;
}
因为我们将
erase
的返回值赋值给
it
,所以我们不必担心迭代器失效。如果我们删除最后一个元素,它将返回
vec.end()
,因此不需要特殊处理

您的第二个循环可以完全删除。C++标准定义了用于在STL容器中搜索的函数。code>std::find_if
搜索满足条件的容器中的值并向其返回迭代器,或者
end()
搜索不存在的值。您还没有在任何地方声明您的类型,所以我将假设行是
std::vector>


提示:除了
erase
方法外,不使用向量特定功能,您可以在每次迭代中删除相同的索引,同时检查大小。您的实际问题不清楚。如果您想知道如何避免在没有GOTO的情况下实现类似的东西,那么很简单,将代码重构为两部分。第一部分是一个使用嵌套循环搜索数组的函数,如果找到匹配项,则生成的索引将获得
return
ed,并在
while
循环中自动断开;第二部分重复调用第一个函数,如果第一个函数找到匹配项,则从两个数组中移除匹配元素,然后重试;或在第一个函数未找到匹配项时停止。结尾。
检查
不应该在第一个
之外,而
?当您擦除
AIVector
的最后一个元素,然后
转到检查时会发生什么情况?请看一下函数,特别是erase-remove示例,以获得一种更简洁、更惯用的方法来处理此类问题。谢谢您的评论。我想我需要多读一些。我是一个上了年纪的C程序员;所以我发现一些C++语法有点压倒了。帕塔流氓,你说得对。如果我使用goto,我就找错地方了。我把它移到了第一次的上方,我的超出范围的错误消失了。不过,我认为我在这里所做的不是
using row_t = std::vector<std::string>;
auto AI_it = AIVector.begin();
while (AI_it != AIVector.end()) {
    // Find a row in TRVector with the same first element as *AI_it
    auto TR_it = std::find_if (TRVector.begin(), TRVector.end(), [&AI_it](const row_t& row) {
        return row[0] == (*AI_it)[0];
    });

    // If a matching row was found
    if (TR_it != TRVector.end()) {
        // Copy the line from AIVector
        auto linevector = *AI_it;

        // Do NOT do this if you don't guarantee size > 3
        assert(TR_it->size() >= 3);
        std::copy(TR_it->begin() + 3, TR_it->end(),
            std::back_inserter(linevector));

        Combo_outputvector.emplace_back(std::move(linevector));

        AI_it = AIVector.erase(AI_it);
        TRVector.erase(TR_it);
    }
    else
        ++AI_it;
}
auto linevector = Combo_outputvector.back();