wordwrap功能

时间:2009-07-05 05:58:55

标签: c++ algorithm word-wrap

嘿伙计们,我正在编写一个自动换行功能来​​格式化C ++中的控制台文本。我的问题是要么A)我不明白std :: string :: iterators究竟做了什么,或者B)我的一个迭代器没有正确设置。任何人都可以解释这段代码失败的原因吗?

顺便说一句:抱歉,如果这个细节太多了。我不确定大多数程序员(我是“新手”)是否在他们的机器上安装了C ++编译器。

std::string wordWrap(std::string sentence, int width)
{    
   //this iterator is used to optimize code; could use array indice 
   //iterates through sentence till end 
   std::string::iterator it = sentence.begin();
   //this iterator = it when you reach a space; will place a newline here
   //if you reach width;
   std::string::iterator lastSpace = sentence.begin();

   int distanceToWidth = 0;

   while (it != sentence.end())
   {
      while (it != sentence.end() && distanceToWidth < width)
      {
         if (*it == ' ')
         {
           lastSpace = it;
         }

         distanceToWidth++;
         it++;
     }

     distanceToLength = 0;
     *lastSpace = '\n';   

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

   return sentence;    
}

我没有得到正确的输出。假设我这样打电话:

std::cout << wordWrap("a b c abcde abcdef longword shtwd", 5) << std::endl << std::endl;
std::cout << wordWrap("this is a sentence of massive proportions", 4) << std::endl;

我对此的结果感到不满意:

a b 
c
abcde
abcdef
longword
shtwd

//yes I get his, instead of this
his is
a
sentence
of
massive
proportions
Press any key to continue . . .

我的问题是我在不适应的时候会得到换行符。我经常收到换行符,但我没有看到任何明显的错误。我希望有人独立(我花了几个小时在这个算法上,并且没有正确的结果是非常令人沮丧的)问题可以看一下。还有,任何明显的优化提示?

4 个答案:

答案 0 :(得分:3)

问题是这个单词是4个字符,并且你用四个字符包装。所以它在将lastSpace设置为合理的东西之前尝试换行。

从单步执行代码来看:

lastSpace points to the "t" from the beginning of "this"
distanceToWidth=0
iterator=this is
         ^

check if we should loop (distanceToWidth<4)
is the current character a space? no
distanceToWidth=1
iterator=this is
          ^

check if we should loop (distanceToWidth<4)
is the current character a space? no
distanceToWidth=2
iterator=this is
           ^

check if we should loop (distanceToWidth<4)
is the current character a space? no
distanceToWidth=3;
iterator=this is
            ^

check if we should loop (distanceToWidth<4)
is the current character a space? no
distanceToWidth=4;
iterator=this is
             ^

check if we should loop (distanceToWidth<4) NO! Because distanceToWidth equals four!

We break out of the loop.

Recall that lastSpace was never modified it still points to the first character in the string!
now we set the "t" character from "this" to be a newline!!

ETC

因此我们在“this”

中输出一个额外的换行符而不是“t”

关于修复它......好吧......你可以搞清楚

答案 1 :(得分:2)

lastSpace迭代器从sentence的第一个字符开始:

//this iterator = it when you reach a space; will place a newline here
//if you reach width;
std::string::iterator lastSpace = sentence.begin();

当你到达“this is a a ...”(空格)的第五个字符时,内部while循环退出(因为distanceToWidth == width),然后才识别出当前字符是空格。然后在位置lastSpace中插入换行符,该换行符仍然指向字符串的第一个字符。这样就失去了“这个”的“t”。

下一个distanceToWidth被重置为零,并且附加了另外width个字符,尽管该行未在当前位置拆分,但在某些字符之前(lastSpace处)。因此,这一行最终可能包含比预期更多的字符。在示例中,“is”仍然与“this”在同一行,而它应该被包装到下一行。

您可能需要:

  • 将内部条件的条件更改为<=,以便检查正确的宽度
  • 未将lastSpace初始化为字符串的第一个字符。可能更好:

<子>

std::string::iterator lastSpace;
...
if (lastSpace) {
   *lastSpace = '\n';
}
  • 计算自上一个空格以来找到的字符数,并在插入换行符后使用此字符重置distanceToWidth

答案 2 :(得分:1)

您的输出与代码显示的内容相符。你错了的是算法。使用调试器找出实际发生的情况。

答案 3 :(得分:0)

更新:这是我的最新代码,显示正确的输出。如果你再读一遍,请评论。对不起格式错误,但在每行前面添加四个空格并且是凌晨1:45是一件麻烦事。

std::string wordWrap(std::string sentence, int width)
{    
//this iterator is used to optimize code; could use array indice 
//iterates through sentence till end 
std::string::iterator it = sentence.begin();
//this iterator = it when you reach a space; will place a newline here
//if you reach width; also kind of hackish (used instead of comparing to NULL)
std::string::iterator lastSpace = sentence.begin();

int distanceToWidth = 0;

//used in rare instance that there is a space
//at the end of a line
bool endOfLine = false;

while (it != sentence.end())
{
   //TODO: possible to stop recomparing against .end()?
   while (it != sentence.end() && distanceToWidth <= width)
   {
      distanceToWidth++;

      if (*it == ' ')
      {
         lastSpace = it;

         //happens if there is a space after the last character
         if (width == distanceToWidth)
         {
            *lastSpace = '\n'; 
         }
      }

      ++it;
   }

   //happens when lastSpace did encounter a space
  //otherwise
   if (lastSpace != sentence.begin())
   {
      *lastSpace = '\n';   
   }       

   lastSpace = sentence.begin();
   distanceToWidth = 0;
   }

   return sentence;    
}