2009-07-05 112 views
2

嗨,大家好,我正在編寫一個單詞封裝函數來格式化C++中的控制檯文本。我的問題是要麼A)我不明白什麼std :: string :: iterators做,或B)我的一個迭代器沒有正確設置。任何人都可以闡明這個代碼失敗的原因嗎?順便說一句:對不起,如果這太詳細了。我不確定大多數程序員(我是「新手」)是否在他們的機器上安裝了C++編譯器。wordwrap函數

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 . . . 

我的問題是,我正在逐漸換行符時不合格的。我越來越頻繁地使用換行符,並且我沒有看到任何明顯的錯誤。我希望有人獨立(我已經花了幾個小時的時間在這個算法上,並且沒有得到正確的結果很令人沮喪),可以看看它。另外,任何明顯的優化技巧?

+0

不,這個問題是範圍特定於我的問題與迭代器。就解決輸出的算法而言,你的回答並不能幫助我。儘管如果您需要,隨時可以關閉此功能,但現在我已經得到了我的答案。 – jkeys 2009-07-05 06:40:36

回答

3

問題後重置distanceToWidth是這個字是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

因此,我們輸出額外的換行符,而不是在「本」

有關解決「T」它......好吧......你可以想出它

+0

謝謝!完美答案,+1 – jkeys 2009-07-05 06:25:33

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(); 

當你達到「這是......」(空格)的第五個字符,內部while循環退出(因爲distanceToWidth == width ),然後識別當前角色是空格。然後在lastSpace位置插入換行符,該位置仍指向字符串的第一個字符。這樣「this」的「t」就會丟失。

接下來distanceToWidth被重置爲零,並且追加了另一個width字符,雖然該行在當前位置未分割,但之前的一些字符(在lastSpace)。所以這行最終可能包含比預期更多的字符。在這個例子中,「is」與「this」仍然在同一行,而它應該被包裝到下一行。

你可能需要:

  • 改變內同時的條件<=,使正確的寬度進行檢查
  • 沒有初始化lastSpace字符串的第一個字符。可能會更好:

std::string::iterator lastSpace; 
... 
if (lastSpace) { 
    *lastSpace = '\n'; 
} 
  • 計數的字符是如何自上次空間中發現,並使用此插入一個換行符
+0

謝謝,正是我需要的。 +1 – jkeys 2009-07-05 06:26:21

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