2016-03-27 78 views
0

我一直在閱讀一本自學的書(http://www.amazon.com/gp/product/0321992784),我正在練習第17章。其中一個我解決了,但我不滿意,希望得到一些幫助。先進的謝謝你。練習:編寫一個從cin中讀取字符的程序到您在免費商店中分配的數組中。閱讀個別字符,直到輸入感嘆號(!)。不要使用std :: string。不要擔心內存耗盡。C++;把字符變成C形字符串

我做了什麼:

​​

我做了2個功能,1到創建一個大小爲1比老款更大一個新的字符串,並在末尾添加一個字符。

char* append(const char* str, char ch) 
/* 
    Create a new string with a size 1 greater than the old 
    insert old string into new 
    add character into new string 
*/ 
{ 
    char* newstr{ nullptr }; 

    int i{ 0 }; 

    if (str) 
     newstr = new char [ sizeof(str) + 2 ]; 
    else 
     newstr = new char [ 2 ]; 

    if(str) 
     while (str [ i ] != '\0') 
      newstr [ i ] = str [ i++ ]; // Put character into new string, then increment the index 

    newstr [ i++ ] = ch; // Add character and increment the index 
    newstr [ i ] = '\0'; // Trailing 0 

    return newstr; 
} 

這是使用我創建的附加功能的鍛鍊,它的工作原理的作用,但是從每個我所說的附加時間我瞭解,有一個內存泄漏,因爲我創建一個新的字符數組,沒」刪除舊的。

char* loadCstr() 
/* 
    get a character from cin, append it to str until ! 
*/ 
{ 
    char* str{ nullptr }; 

    for (char ch; std::cin >> ch && ch != '!';) 
     str = append(str, ch); 

    return str; 
} 

我嘗試添加另一個指針持有舊陣列,使一個新的後予以刪除,但在經過這個循環約6呼叫我得到一個運行時錯誤,我想告訴我,我刪除我的東西不應該?這是我困惑的地方。

這是舊的,不超過6個字符的工作:

char* loadCstr() 
/* 
    get a character from cin, append it to str until ! 
*/ 
{ 
    char* str{ nullptr }; 

    for (char ch; std::cin >> ch && ch != '!';) { 

     char* temp{ append(str, ch) }; 

     if (str) 
      delete str; 

     str = temp; 
    } 
    return str; 
} 

所以我想知道這樣有沒有內存泄漏我如何解決此問題的功能。再次感謝你。 (另請注意,我知道這些函數已經存在,使用std :: string可以處理所有免費商店的東西,我只是想了解它,這是一個學習練習。)

+0

讓呼叫者釋放內存 – stackptr

+0

'sizeof(str)'和'strlen(str)'是不一樣的 –

+0

@stackpt r是的,當loadCstr()調用追加時,我試圖在將temp放入它之前刪除str,但是在循環有6個循環後我得到一個運行時錯誤。如果我刪除主要字符串,這不意味着每次我調用append(str,ch)我泄漏str? –

回答

0

您必須使用標準C函數std::strlen而不是sizeof運算符,因爲在您的函數中,sizeof運算符返回指針的大小而不是字符串的長度。

此外,您還需要刪除已分配的數組。

功能可以看看下面的方式

char* append(const char* str, char ch) 
/* 
    Create a new string with a size 1 greater than the old 
    insert old string into new 
    add character into new string 
*/ 
{ 
    size_t n = 0; 

    if (str) n = std::strlen(str); 

    char *newstr = new char[ n + 2 ]; 

    for (size_t i = 0; i < n; i++) newstr[i] = str[i]; 

    delete [] str; 

    newstr[n] = ch; 
    newstr[n+1] = '\0'; 

    return newstr; 
} 

而且在功能loadCstr它可以被稱爲像

str = append(str, ch); 

,而不是循環複製該字符串還可以使用標準算法std::copy

+0

我在迴避標準庫函數,因爲這是一個學習練習,但你的答案仍然正確。我重新創建了strlen(),我將重新創建副本,但主要問題是我使用sizeof(),它從來沒有給我實際的字符數,它只給了我字符串的字節數。謝謝 –

+0

@MATC根本沒有。不用謝。:) –

0

是要學點關於內存管理,還是關於字符串操作如何在內部工作?

對於第二個(學習字符串操作),您應該使用std::unique_ptr<char[]>,它將在指針死亡時自動釋放所連接的數組。你仍然需要計算字符串長度,字符串之間的複製,追加 - 你現在正在做的所有事情。但std::unique_ptr<char[]>將處理重新分配。

對於第一種情況,您最好是寫一個RAII類(定製版本爲std::unique_ptr<T>),並學習如何在析構函數中釋放內存,而不是在您的代碼中散佈delete []聲明。隨處編寫delete []實際上是一個壞習慣,學習它會提高你向後編程C++的能力。