简体   繁体   English

表达式:不可迭代的字符串迭代器

[英]Expression: String iterator not dereferencable

I'm having a hard time using std::string::iterators in C++. 我在C ++中使用std :: string :: iterators遇到困难。 This code compiles fine (still not getting correct output, but that's my fault: TODO, fix algorithm) in Dev-C++, and I don't get runtime errors. 这段代码在Dev-C ++中可以很好地编译(仍然无法获得正确的输出,但这是我的错:TODO,修复算法),而且我没有遇到运行时错误。 The error is with Visual Studio Express 2008 C++, where I'm getting an error pointing to < xstring>: "Expression: string iterator not dereferencable," and points to line 112 of the < xstring> file. 该错误与Visual Studio Express 2008 C ++有关,在这里我得到一个指向<xstring>的错误:“表达式:字符串迭代器不可解除引用”,并指向<xstring>文件的第112行。

My debugging tells me I might be trying to dereference past the end of the sentence input, but I can't see where. 我的调试告诉我,我可能正在尝试在句子输入末尾取消引用,但看不到哪里。 Can anyone shed some light? 谁能阐明一些想法?

std::string wordWrap(std::string sentence, int width)
{    
    std::string::iterator it = sentence.begin();

    //remember how long next word is
    int nextWordLength = 0;
    int distanceFromWidth = width;

    while (it < sentence.end())
    {
       while (*it != ' ' && it != sentence.end())
       {
          nextWordLength++;
          distanceFromWidth--;
          it++;
       }

       if (nextWordLength > distanceFromWidth)
       {
          *it = '\n';
          distanceFromWidth = width;
          nextWordLength = 0;
       }

       //skip the space
       it++;

   }

   return sentence;    
}

Firstly, use operator!=() on iterators, not operator<(): 首先,在迭代器上使用operator!=(),而不要在operator <()上使用:

while (it != sentence.end())

Secondly, this is backwards: while (*it != ' ' && it != sentence.end()) 其次,这是倒退的: while (*it != ' ' && it != sentence.end())

You do something with the iterator, than check if the iterator is valid. 您需要对迭代器进行操作,而不是检查迭代器是否有效。 Rather, you should check if it's valid first: 相反,您应该首先检查它是否有效:

while (it != sentence.end() && *it != ' ')

Thirdly, you should use ++iterator over iterator++, though this isn't related to your crashing. 第三,您应该在迭代器上使用++ iterator ++,尽管这与崩溃无关。


Fourth, a main issue is here: 第四,主要问题在这里:

*it = '\n';

Because of the preceeding check, while (it != sentence.end() , it's possible to reach that iterator dereference while being at the end. A fix would be to do this: 由于前面的检查, while (it != sentence.end() ,则可能在结束时达到该迭代器的取消引用。解决方法是:

if (it != sentence.end() && nextWordLength > distanceFromWidth)

So now if you have reached the end, you stop. 所以现在,如果您已结束,请停止。


After fixing the previous issue, now the only problem is this: 解决了上一个问题之后,现在唯一的问题是:

//skip the space
++it;

This assumes that the character you are skipping is in fact a space. 这假定您要跳过的字符实际上是一个空格。 But what about the end of the string? 但是字符串的结尾呢? Run this function with this string: 使用以下字符串运行此函数:

"a test string " // <- space at end

And it will succeed; 它会成功; it skips the space, putting the iterator at end() , the loop exits and success. 它跳过空间,将迭代器放在end() ,循环退出并成功。

However, without the space it will crash, because you have reached the end, and are skipping past the end. 但是,如果没有空间,它将崩溃,因为您已经到达终点,并且正在跳过终点。 To fix, add a check: 要修复,请添加检查:

//skip the space
if (it != sentence.end())
{
    ++it;
}

Resulting in this final code: 最终代码如下:

std::string wordWrap(std::string sentence, int width)
{    
    std::string::iterator it = sentence.begin();

    //remember how long next word is
    int nextWordLength = 0;
    int distanceFromWidth = width;

    while (it != sentence.end())
    {
        while (it != sentence.end() && *it != ' ')
        {
            nextWordLength++;
            distanceFromWidth--;
            ++it;
        }

        if (it != sentence.end() && nextWordLength > distanceFromWidth)
        {
            *it = '\n';
            distanceFromWidth = width;
            nextWordLength = 0;
        }

        //skip the space
        if (it != sentence.end())
        {
            ++it;
        }

    }

    return sentence;    
}

You might notice this seems like it has a lot of redundant checks. 您可能会注意到,这似乎有很多多余的检查。 This can be fixed: 这可以解决:

std::string wordWrap(std::string sentence, int width)
{    
    std::string::iterator it = sentence.begin();

    //remember how long next word is
    int nextWordLength = 0;
    int distanceFromWidth = width;

    while (it != sentence.end())
    {
        while (*it != ' ')
        {
            nextWordLength++;
            distanceFromWidth--;

            ++it;

            // check if done
            if (it == sentence.end())
            {
                return sentence;
            }
        }

        if (nextWordLength > distanceFromWidth)
        {
            *it = '\n';
            distanceFromWidth = width;
            nextWordLength = 0;
        }

        //skip the space
        ++it;
    }

    return sentence;    
}

Hopefully that helps! 希望有帮助!

while (*it != ' ' && it != sentence.end())

changes to 更改为

while (it != sentence.end() && *it != ' ')

so the second expression isn't evaluated if the first if false. 因此,如果第一个表达式为false,则不会计算第二个表达式。

   if (nextWordLength > distanceFromWidth)

should probably change to 应该更改为

   if (it == sentence.end())
         break;
   if (nextWordLength > distanceFromWidth)

Almost certainly your error is the result of: 几乎可以肯定,您的错误是由于以下原因造成的:

*it = '\n';

Since in the preceding while loop one of your stopping conditions is: 由于在前面的while循环中,您的停止条件之一是:

it != sentence.end()

If it == sentence.end(), then *it = '\\n' won't fly 如果它==句子.end(),则* it ='\\ n'不会飞

There are more errors, but that's the one that's causing your current problem. 还有更多错误,但这是导致当前问题的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM