2

大家好,我正在编写一个自动换行函数来格式化 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

4 回答 4

3

问题是这个词是 4 个字符,而你用 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”

关于修复它......嗯......你可以弄清楚

于 2009-07-05T06:19:49.330 回答
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...”的第五个字符(空格)时,内部 while 循环退出(因为distanceToWidth == width),然后才识别出当前字符是空格。然后在 position 中插入一个换行符lastSpace,它仍然指向字符串的第一个字符。这样,“this”的“t”就丢失了。

NextdistanceToWidth重置为零并width附加另一个字符,虽然该行没有在当前位置拆分,但在 (at lastSpace) 之前有一些字符。所以这一行最终可能包含比预期更多的字符。在这个例子中,“is”仍然和“this”在同一行,而它应该被换到下一行。

您可能需要:

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

std::string::iterator lastSpace;
...
if (lastSpace) {
   *lastSpace = '\n';
}
  • 计算自最后一个空格以来找到了多少个字符,并distanceToWidth在插入换行符后使用它来重置
于 2009-07-05T06:16:42.173 回答
1

从您的代码显示的内容来看,您的输出是正确的。你错的是算法。使用调试器找出实际发生的情况。

于 2009-07-05T06:15:05.483 回答
0

Update: here is my latest code, showing correct output. Please comment if you read this again. Sorry for bad formatting, but it's a hassle to add four spaces in front of each line and it is 1:45 AM.

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;    
}
于 2009-07-05T07:44:48.337 回答