C++ 为什么在遍历这个向量时会出现分段错误?

C++ 为什么在遍历这个向量时会出现分段错误?,c++,vector,iterator,std,C++,Vector,Iterator,Std,我需要遍历这个向量并删除重复项。此代码中的某个位置出现分段错误。我的猜测是,它与迭代器运行时删除元素有关,但我对迭代器的实际工作方式还没有具体的了解,所以我无法理解 vector<char *>::iterator iter; for (iter = v->begin(); iter != v->end()-1; iter++ ){ char *aString = *iter; int n = 1; while(iter+n != v->en

我需要遍历这个向量并删除重复项。此代码中的某个位置出现分段错误。我的猜测是,它与迭代器运行时删除元素有关,但我对迭代器的实际工作方式还没有具体的了解,所以我无法理解

vector<char *>::iterator iter;
for (iter = v->begin(); iter != v->end()-1; iter++ ){
    char *aString = *iter;
    int n = 1;
    while(iter+n != v->end()){
        int comparison = strcmp(aString, *(iter+n));
        if(comparison == 0){
            v->erase(iter + n);
        }
        n++;
    }
}
vector::迭代器iter;
对于(iter=v->begin();iter!=v->end()-1;iter++){
char*aString=*iter;
int n=1;
而(iter+n!=v->end()){
int比较=strcmp(aString,*(iter+n));
如果(比较==0){
v->擦除(iter+n);
}
n++;
}
}

从向量中删除一个元素时,该向量会缩短一个元素。试试这个:

if(comparison == 0){
  v->erase(iter + n);
}
else{
  n++;
}

从向量中删除一个元素时,该向量将缩短一个元素。试试这个:

if(comparison == 0){
  v->erase(iter + n);
}
else{
  n++;
}

您没有正确地遍历向量的其余部分。Beta版建议的另一种方法是使用remove-remove和remove\u if。像这样:

bool compare_strings(char * aString,char * bString)
{
    return 0==strcmp(aString,bString);
}

void remove_duplicates(vector<char *> * v)
{
    vector<char *>::iterator iter;
    for (iter = v->begin(); iter != v->end(); iter++ ) {
        v->erase(std::remove_if(iter+1,v->end(),compare_strings),v->end());
    }
}
bool比较字符串(char*aString,char*bString)
{
返回0==strcmp(aString,bString);
}
无效删除重复项(向量*v)
{
向量:迭代器iter;
对于(iter=v->begin();iter!=v->end();iter++){
v->erase(std::remove_if(iter+1,v->end(),compare_strings),v->end());
}
}

未正确迭代向量的其余部分。Beta版建议的另一种方法是使用remove-remove和remove\u if。像这样:

bool compare_strings(char * aString,char * bString)
{
    return 0==strcmp(aString,bString);
}

void remove_duplicates(vector<char *> * v)
{
    vector<char *>::iterator iter;
    for (iter = v->begin(); iter != v->end(); iter++ ) {
        v->erase(std::remove_if(iter+1,v->end(),compare_strings),v->end());
    }
}
bool比较字符串(char*aString,char*bString)
{
返回0==strcmp(aString,bString);
}
无效删除重复项(向量*v)
{
向量:迭代器iter;
对于(iter=v->begin();iter!=v->end();iter++){
v->erase(std::remove_if(iter+1,v->end(),compare_strings),v->end());
}
}

从向量中擦除会使从擦除开始的所有迭代器失效,因此您可能不应该像这样构造循环,而应该使用以下标准习惯用法:

for (auto it = v.begin(); it != v.end(); ++it)   // no end() - 1 -- may not be legal!
{
  for (auto jt = it; jt != v.end(); )
  {
    if (jt == it) continue;

    if (strcmp(*it, *jt) == 0)
    {
      jt = v.erase(jt);
    }
    else
    {
      ++jt;
    }
  }
}

此代码避免了对空向量的检查,而空向量是您的代码无法解释的。

从向量中擦除会使从擦除开始的所有迭代器失效,因此您可能不应该像这样构造循环,而应该使用以下标准习惯用法:

for (auto it = v.begin(); it != v.end(); ++it)   // no end() - 1 -- may not be legal!
{
  for (auto jt = it; jt != v.end(); )
  {
    if (jt == it) continue;

    if (strcmp(*it, *jt) == 0)
    {
      jt = v.erase(jt);
    }
    else
    {
      ++jt;
    }
  }
}

这段代码避免了对空向量的检查,而您的代码无法解释空向量。

真的,您只需要在这里逐个解决几个问题。删除元素时,您与
end()
n
的比较不正确:

for (iter = v->begin(); iter != v->end()-1; iter++ ){
                                  ^^^^^^^^

以下内容将满足您的要求(并证明其有效):

intmain()
{
std::向量v(4,“this”);
std::vector::iter;
对于(iter=v.begin();iterstd::cout真的,您在这里遇到了一对一的问题。当您擦除一个元素时,您与
end()
和递增
n
进行了错误的比较:

for (iter = v->begin(); iter != v->end()-1; iter++ ){
                                  ^^^^^^^^

以下内容将满足您的要求(并证明其有效):

intmain()
{
std::向量v(4,“this”);
std::vector::iter;
对于(iter=v.begin();iter
std::仍然不能得到分段错误吗?仍然不能得到分段错误吗?不要猜测。在调试器中运行它,并找出导致分段错误的原因。向量可能不是空的,是吗?@weezybizzle-看到我的答案,你的代码中确实只有几个小错误。不要猜测。在调试器并找出导致seg错误的原因。向量可能不是空的,是吗?@weezybizzle-看到我的答案了吗,你的代码中确实只有几个小错误。他没有删除迭代器引用的元素,所以它不会失效(或者我遗漏了什么?)。您需要将n初始化为1,否则它会将字符串与自身进行比较。@IronMensan:已修复!请注意,我坚持从零开始,这样我们就不需要额外的非空检查。@KerrekSB-请检查您的答案;他并没有使迭代器无效。他只是有一对一的问题。我不理解您关于使用的评论
strncmp
。为什么向量中的
char*
s会指向向量本身?std::distance(it+n,v.end())
char*
指向的内存有什么关系?他没有删除迭代器引用的元素,所以它不会失效(或者我遗漏了什么?)。您需要将n初始化为1,否则它会将字符串与自身进行比较。@IronMensan:已修复!请注意,我坚持从零开始,这样我们就不需要额外的非空检查。@KerrekSB-请检查您的答案;他并没有使迭代器无效。他只是有一对一的问题。我不理解您关于使用的评论
strncmp
。为什么向量中的
char*
s会指向向量本身?距离(it+n,v.end())
char*
s指向的内存有什么关系?这对我来说是可行的,非常感谢。v.end()也是如此指向向量中的最后一个元素?或者它有点像字符串中的空终止符,只是一个指定结束的元素?@weezybizzle-
vector.end()
返回一个迭代器,该迭代器引用向量容器中结束元素的过去,而不是最后一个元素。Your
iter!=v.end()-由于擦除,向量中只剩下1个元素,然后迭代器增加到
v.end()
。你可以写
iter Ok,这很有道理。非常感谢@BrianRoachThats为我解决了问题,非常感谢。v.end()也是如此指向向量中的最后一个元素?或者它有点像字符串中的空终止符,只是一个指定t的元素