2010-08-20 89 views
2

我有一個簡單的函數,它檢查給定的字符串是否匹配某個條件,然後根據收到的2個字符串生成第三個字符串作爲參數。第三個字符串很好,但當我返回時,它突然變成「\n」。退出循環時字符串更改的內容

string sReturn = ""; 
if (sText.size() != sPassword.size()) { 
    //Checks to see if the texts match a condition 
    return sReturn; 
} 
for (int foo = 0; foo < sText.size(); foo++) { 
    sReturn = ""; 
    sReturn += (char)sText[foo]^(char)sPassword[foo]; 
} 
return sReturn; 

在爲sReturn優良並具有正確的內容,但只要它存在循環,調試器突然告訴我,它的內容是「\n」。我究竟做錯了什麼 ?

+6

僅供參考:只有通過for循環的最後一次迭代實際上會產生任何效果,因爲每次循環體開始時都會清空sReturn。 – 2010-08-20 15:48:36

+0

您應該作出答覆James – mnuzzo 2010-08-20 15:49:54

+0

顯示函數定義及其使用位置。 – 2010-08-20 15:50:13

回答

3
  1. 你不必用空字符數組一樣來初始化字符串 :

    std::string sReturn = ""; 
    

    Default constructor爲了做它 你和效率要高得多。 正確的代碼:

    std::string sReturn; 
    
  2. 分配一個空字符串在你的循環每次迭代sReturn 是 不正確。更何況,以 明確的字符串你必須調用 std::string::clear()

    sReturn = ""; 
    

    正確的代碼:

    sReturn.clear(); 
    

    但這應該從 循環都在你的情況下被刪除。

  3. 沒有需要明確 運營商[] (爲size_t)的結果轉換成字符,因爲它 是一個字符:

    sReturn += (char)sText[foo]^(char)sPassword[foo]; 
    

    正確的代碼:

    sReturn += sText[foo]^sPassword[foo]; 
    
  4. 使用post-increment代替 循環是沒有必要的。它使每個 增量的「富」的 額外副本:

    for (int foo = 0; foo < sText.size(); foo++) 
    

    這可能會 編譯器優化,但你必須擺脫的 這個壞習慣。改爲使用 pre-increment。正確 代碼:

    for (int foo = 0; foo < sText.size(); ++foo) 
    
  5. 調用的std :: string ::大小()上 每次迭代時字符串大小 不會改變效率不高:

    for (size_t foo = 0; foo < sText.size(); ++foo) 
    

    更好的代碼:

    for (size_t foo = 0, end_foo = sText.size(); foo < end_foo; ++foo) 
    

    注意size_t類型。你不能存儲 字符串大小在32位有符號整數 ,因爲它沒有足夠的容量,以 存儲大量。正確的類型是 size_t,它由 std :: string :: size()方法返回。

考慮到所有上述情況,正確的功能應該是這個樣子:

std::string 
getMixedString (const std::string & text, const std::string & password) 
{ 
    std::string result; 
    if (text.length() != password.length()) 
     return result; 
    for (size_t pos = 0, npos = text.length(); pos < npos; ++pos) 
     result += text[pos]^password[pos]; 
    return result; 
} 

但有,如果你想最後一個字符串是人類可讀的一個問題。在兩個ASCII字符上使用eXclusive OR(XOR)運算符可能會或可能不會爲您提供人類可讀的字符,甚至不會爲您提供字符。所以你可能會得到結果字符串,其中包含換行符,無法讀取的字符,無論如何都會有一些garbage

爲了解決這個問題,你必須想出一些更好的算法來生成基於其他兩個字符串的字符串。例如,您可以使用兩個字符串的MD5散列或將它們編碼爲base64

祝你好運!

+0

非常感謝您的回答。直到現在我才注意到,我已經把線條放在了圈內,這是一個沒有注意力的錯誤。我還在您的答案中發現了很多其他一些我不知道的信息,這些信息可能有助於改進我的代碼。不過,我仍然有一個問題。每次在調試器監視窗口中執行循環時,字符串變得越來越大(顯然忽略了字符串清除),最後變成「\ n」。 – Andrew 2010-08-20 16:42:02

+0

你是什麼意思'字符串變得越來越大' – Falmarri 2010-08-20 17:12:24

+0

如果你認爲他每次迭代都輸出字符串(用於調試),那麼我認爲他的意思是它一次輸出一個字符......例如,如果輸出字符串「ABCDE」是*內置*一次一個字符,則每次通過循環時,都會出現「AABABCABCDABCDE」。在這種情況下,它只輸出一個字符(因爲那是字符串中的所有字符)並且正在變爲「ABCDE」。容易錯過錯誤,因爲它是你「期待」的字符串 – 2010-08-20 17:52:08

3

爲什麼你有sReturn = ""裏面的循環。在循環之前不應該初始化嗎?

在給定的情況下sReturn將只有一個字符。在你的情況下,我會假設^操作在最後一次迭代中產生一個\ n字符。

2

您已經解決了該問題。我會提出一種完全不同的做事方式,我認爲這樣做可以消除產生類似錯誤的大多數可能性。首先,我將「編碼」部分中的「檢查文本是否匹配條件」部分分開。現在,你有一個(相當小的)代碼似乎有兩個,主要是無關的責任。

的編碼部分,我會寫這樣的事:

struct encode_byte { 
    char operator()(char a, char b) { 
     return a^b; 
    } 
}; 

std::transform(sText.begin(), sText.end(), 
       sPassword.begin(), sPassword.end(), 
       std::back_inserter(sResult), 
       encode_byte()); 
+0

我在編程方面是初學者,特別是C++,所以你可以向我解釋這段代碼嗎?據我所見,你超載一個操作員,但我迷路了。 – Andrew 2010-08-21 03:20:37

+0

我已經做了一些閱讀,現在我明白了轉換函數是如何工作的(將函數應用於範圍)並且已經重載了'()'運算符。感謝這個想法。 – Andrew 2010-08-21 03:28:19

2
string sReturn; 
if (sText.size() != sPassword.size()) { 
     return sReturn; 
} 
for (size_t foo = 0, end_foo = sText.size(); foo < end_foo; ++foo) { 
     sReturn += sText[foo]^sPassword[foo]; 
} 
return sReturn; 

我已經重寫了,現在每個人使用的技巧。我對由於不注意造成的錯誤表示歉意 - 每次運行循環時清除字符串。我希望現在可以,請告訴我是否有任何問題。感謝大家提供的答案。

+0

PS:任何人都會告訴我爲什麼最後一個字符總是退格?無論使用什麼字符串,總是字符是10(BS,退格)的ASCII碼。 – Andrew 2010-08-20 16:59:31