char *

2017-04-26 120 views
-2

C++動態分配我在下面的一段代碼中遇到了一個問題,問題就是動態分配的char *數組的值從第24行變爲第28行,而我無法確定爲什麼char *

代碼:

#include <iostream> 
#include <string> 
#include <stdlib.h> 
#include <ctype.h> 
#include <cstring> 

using namespace std; 

int main() { 
    string x = "5+90-88n"; 
    unsigned int i =0, k=0, argc=0; 
    char** argv = new char*[x.length()]; 

    while (i < x.length()) { 
    if (isdigit(x[i])) { 
     k=0; 
     while (isdigit(x[i+k])) {k++;} 
     argv[argc] = (char*)x.substr(i,k).c_str(); 
     i+=k; 
    } else { 
     argv[argc] = (char*)x.substr(i,1).c_str(); 
     i++; 
    } 
    cout << argc <<" "<< argv[argc] <<endl; 
    argc++; 
    } 

    cout << " ------ \n"; 
    for (unsigned int kk =0; kk<argc; kk++) { 
    cout << kk << " " << argv[kk] << endl; 
    } 

    return 0; 
} 

輸出:

0 5 
1 + 
2 90 
3 - 
4 88 
5 n 
------ 
0 n 
1 n 
2 n 
3 n 
4 n 
5 n 

我期待的上部和下部是一樣的,是不是,即使有一些失誤同樣的手段我做了,沒有注意到,或者有些我不知道使用動態分配的東西。

+1

你爲什麼亂搞char *數組?使用字符串的向量。 –

+0

我知道向量更好,但我不確定在我的任務中使用它們,因爲這是賦值的一部分,但上述部分會導致主要問題 –

+0

您爲*指針*分配內存,但不爲字符串分配內存。 –

回答

2

返回指針指向的數組std::string::c_strstring所有。 substr返回在調用substr的表達式結尾處超出範圍的臨時對象string

將這兩個事實放在一起意味着argv中的指針所指向的數組在創建後立即被刪除。當你開始打印他們的任何一個時,他們已經很久了。

0

這似乎是一個簡單的問題,但實際上並沒有,我花了幾個小時試圖找到答案。 讓我們來看看下面這段代碼:

int main() 
{ 
    const char* p; 
    const char* p1; 
    { 
    string x = "xt"; 
    p = x.substr(0, 1).c_str(); 
    cout << p << endl; 
    p1 = x.substr(1, 1).c_str(); 
    cout << p1 << endl; 
} 
cout << p << endl; 
cout << p1 << endl; 
return 0; 
} 

它的輸出是:

x 
t 
t 
t 

當{}範圍,對運行和P1都指向臨時變量,現在這些變量存在,所以我們可以打印出p1。當代碼超出{}作用域時,那些臨時變量不存在,我們不能再引用它們,但它們的內存和數據仍然存在。所以我們仍然可以在沒有內存崩潰的情況下打印出p和p1的值。 但爲什麼p和p1的值是相同的? 讓我們來看看這個:

int main() 
{ 
    const char* p; 
    const char* p1; 
    { 
    string x = "xt"; 
    string t1 = x.substr(0, 1); 
    p = t1.c_str(); 
    cout << p << endl; 
    string t2 = x.substr(1, 1); 
    p1 = t2.c_str(); 
    cout << p1 << endl; 
} 
cout << p << endl; 
cout << p1 << endl; 
return 0; 
} 

它的輸出是:

x 
t 
x 
t 

就像你的預期。 也許在substr有什麼奇怪的地方。但我不確定。我會繼續檢查。 而且,如上面的代碼所示,p和p1指向不同的臨時變量,根據不同的輸出,在第一個示例中,p和p1可能指向相同的臨時變量。 讓我們回到你的代碼,char **是指向指針的指針,經常使指針指向一個臨時變量是錯誤的。 我的建議是,你可能會使用一組string而不是一個指針數組。 希望有所幫助。

+0

謝謝你的回答,但我真的沒有' t得到你寫的兩個代碼的核心區別 –

+0

在第一個例子中,臨時字符串由substr()創建,在第二個例子中,我聲明t1和t2取臨時變量的值。這是不同的。 –

+0

我做了這樣的事情: string y1,y2,x =「5 + 90-88n」; 然後: y1 = x.substr(i,k); argv [argc] =(char *)y1.c_str(); 和y2相同, 我得到了不同的結果,但問題仍然存在,因爲它是 –

0

您不會爲創建的臨時子字符串字符串對象分配任何內容,該對象會創建一個指向數組的臨時指針。

做這樣的事情應該工作,但不推薦,因爲你不能釋放內存了:

argv[argc] =(char*)((new string(x.substr(i,k)))->c_str()); 

你需要的字符串對象生存爲c_str返回一個常量字符串指針對象的值。如果字符串對象不存在,該指針指向什麼?閱讀:c_str cplusplus.com

建議儲存子字符串數組的一些/向量,然後做必要的工作的指針。

0

@Mohamed易卜拉欣,我想我已經得到了這個問題,這兩個輸出是不同的真正原因。 讓我們首先考慮一個問題:

臨時變量結束其生命期時發生了什麼?

請參閱此代碼:

int a1 = 9; 
int& a = a1; 
{ 
    int b = 10; 
    a = b; 
    cout << a << endl; 
    int c = 11; 
    count << a << endl; 
} 
cout << a << endl; 

其輸出是:

10 
11 
11 

但我們知道,'b''c'已經當我們嘗試打印'a'出在最後的時間。爲什麼'a'仍然有價值?

的原因是'b''c'儘管'b''c'仍然存在已經走了存儲器和數據。 'a'是參考,它指的是'b''c'的記憶。

讓我們繼續考慮:

當將內存和一個臨時變量的數據被掃?

即使臨時壽命已經結束,但其內存和數據仍然存在,直到聲明另一個臨時變量,並且新變量的值覆蓋該內存中舊變量的值,然後所有指針和引用這些舊變量的引用,它們的值已被更改,我們可以打印出它們的值來證明。 因此,在您的代碼中,儘管可以打印出正確的值,但每個循環中都會聲明一個新的臨時變量string,但新變量已覆蓋舊的變量。在while範圍結束後,只有一個變量的值是現有的,它是你聲明的最後一個變量,所有的人都被覆蓋。所以,我們可以在上次輸出中看到相同的值。

保持每個值的方法是將其保存在一個全局變量:

int main() 
{ 
    string x = "5+90-88n"; 
    unsigned int i =0,k=0,argc=0; 
    char** argv = new char*[x.length()]; 

    while (i< x.length()) 
{ 
    if (isdigit(x[i]))   { k=0; 
         while(isdigit(x[i+k])) {k++;} 
         char* temp = (char*)x.substr(i,k).c_str(); 
         argv[argc] = new char[strlen(temp) + 1]; 
         memset(argv[argc], 0, sizeof(argv[argc])); 
         strcpy(argv[argc], temp); 
         i+=k; 
        } 
    else    { 
        char* temp = (char*)x.substr(i,1).c_str(); 
         argv[argc] = new char[strlen(temp) + 1]; 
         memset(argv[argc], 0, sizeof(argv[argc])); 
         strcpy(argv[argc], temp); 
        i++; 
        } 
cout << argc <<" "<< argv[argc] <<endl; 
argc++; 
} 
cout<<" ------ \n"; 
for(unsigned int kk =0;kk<argc;kk++) { cout <<kk <<" "<<argv[kk]<<endl; } 

return 0; 
} 

上面的代碼可以很好地工作,但它是不安全的,我不喜歡編碼的這種方式。 正如我所說過的,我的建議不要試圖將指針指向臨時變量,從不這樣做。沒有冒犯,請糾正你的代碼。