自动换行功能

Posted

技术标签:

【中文标题】自动换行功能【英文标题】:wordwrap function 【发布时间】:2009-07-05 05:58:54 【问题描述】:

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

我的问题是我在不合适时收到换行符。我经常收到换行符,我没有看到任何明显的错误说明为什么会这样。我希望独立的人(我在这个算法上花了几个小时,没有正确的结果是非常令人沮丧的)可以看看这个问题。另外,有什么明显的优化技巧吗?

【问题讨论】:

不,这个问题是针对我的迭代器问题的范围。就修复输出算法而言,您的回答对我没有帮助。虽然如果你需要可以关闭这个,现在我有我的答案了。 【参考方案1】:

问题是这个词是 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”

关于修复它......好吧......你可以解决它

【讨论】:

【参考方案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),然后才识别出当前字符是空格。然后在lastSpace 位置插入一个换行符,它仍然指向字符串的第一个字符。这样“this”的“t”就丢失了。

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

您可能需要:

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

std::string::iterator lastSpace;
...
if (lastSpace) 
   *lastSpace = '\n';

计算自最后一个空格以来找到了多少个字符,并在插入换行符后使用它来重置distanceToWidth

【讨论】:

谢谢,正是我需要的。 +1【参考方案3】:

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

【讨论】:

【参考方案4】:

更新:这是我最新的代码,显示正确的输出。如果您再次阅读此内容,请发表评论。抱歉格式错误,但在每行前面添加四个空格很麻烦,现在是凌晨 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;    

【讨论】:

以上是关于自动换行功能的主要内容,如果未能解决你的问题,请参考以下文章

具有自动换行功能的 UITextField

自动换行功能

怎样设置xshell自动换行

记事本的自动换行功能和显示状态栏不能同时打开

PHP php自动换行功能

idea 如何取消自动换行设置?