2009-06-30 45 views
0

我很难在C++中使用std :: string :: iterators。这段代码在Dev-C++中编译得很好(仍然没有得到正确的输出,但那是我的错:TODO,修复算法),并且我没有得到运行时错误。错误是在Visual Studio Express 2008 C++中,我得到一个指向< xstring>:“Expression:string iterator not derefereenable”的错误,并指向< xstring>文件的第112行。表达式:字符串迭代器不可忽略

我的调试告诉我,我可能试图解引用过去的句子输入结束,但我看不到在哪里。任何人都可以点亮一下吗?

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;  
} 

回答

15

首先,使用操作符=()的迭代器,而不是运营商<():

while (it != sentence.end()) 

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

你用迭代器做了一些事情,而不是检查迭代器是否有效。相反,你应该检查是否是有效的第一:

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

第三,你应该使用了迭代器++ ++迭代器,虽然这是不相关的崩溃。


第四,一个主要的问题是在这里:

*it = '\n'; 

由于前述检查,while (it != sentence.end()的,有可能达到这个迭代器提领,同时在最后。解决办法是做到这一点:

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

所以现在如果你已经到了最后,你停下来。


固定之前的问题后,现在唯一的问题是这样的:

//skip the space 
++it; 

这假定您跳过的字符实际上是一个空间。但是,字符串的结尾呢?与此字符串运行这个功能:

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

它会成功;它跳过空间,将迭代器置于end(),循环退出并成功。

但是,没有空间它会崩溃,因为你已经到了最后,并且正在跳过最后。要修复,添加一个检查:

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

在这最后的代码得到的:

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;  
} 

您可能会注意到这似乎是它有很多冗余检查。这可以是固定的:

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;  
} 

希望帮助!

+0

+1。我已经纠正了第2点中的代码,以使其与代码的完整代码块和解释一致。 – 2009-06-30 07:22:09

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

更改

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

所以第二个表达式不评估如果第一如果为假。

if (nextWordLength > distanceFromWidth) 

或许应该改为

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

几乎可以肯定你的错误的结果是:

*it = '\n'; 

由于同时你停止状况一环就是前面:

it != sentence.end() 

如果== sentence.end()那么* it ='\ n'不会飞

还有更多的错误,但这是造成您目前的问题。