簡體   English   中英

沒看懂 C++ 堆棧<char*>行為</char*>

[英]Did not understand C++ stack<char*> behavior

我被困了兩個小時,試圖了解這個簡單的 C++ 測試程序中發生了什么,但仍然沒有得到它。 它應該只接收三個字符串作為輸入,將它們插入堆棧,最后打印同一堆棧的所有元素。

#include <iostream>
#include <stack>
#include <cstring>

using namespace std;

int main(){
    
    stack<char*> stk;
    
    int stringLength;
    
    for (int i=0; i<3; i++){
        char new_element[200];
        scanf("%s", new_element);
        stringLength = strlen(new_element);
        stk.push(new_element);
    }
    
    cout << "Stack content: ";
    while(!stk.empty()){
        cout << stk.top() << " ";
        stk.pop();
    }
    cout << endl;

}

奇怪的是,最終的 output 是相同的元素(最后添加的)打印了 3 次,這對我來說毫無意義。

例如,如果輸入是:

John
Mary
Rick

那么當前的 output 是

Rick
Rick
Rick

誰能幫我理解和解決這個問題?

    char new_element[200];
    // [...]
    stk.push(new_element);

您在堆棧 object 中推送相同的指針。

更糟糕的是,您正在推送系統堆棧指針,因此如果您要從 function 外部使用堆棧,您會遇到訪問沖突(Linux 中的段錯誤)並崩潰。 在您的情況下,您並沒有從外部使用它們,因為堆棧 object 也在堆棧上。

無論如何,有兩個快速修復:

  1. 編寫正確的代碼:使用string並讓編譯器找出復制它們並根據需要清理它們。

  2. 不要編寫正確的代碼:使用strdup獲取唯一的字符串指針。 您可能希望或不希望在某個時候釋放它們,對於選擇這條路線的人來說,這似乎總是可選的。

因為您已將stk聲明為std::stack<char*> ,所以它的元素將是char* ,或指向char數據的指針(即地址)。

那么,執行stk.push(new_element);時你會做什么行是將您的(本地)字符數組的地址放入堆棧中。 從技術上講,當您稍后pop該地址並打印它指向的字符串時,您正在執行未定義的行為,因為指向的 memory 已超出 scope (它的“生命周期”只是第一個for循環的一次迭代)。

但是,您的系統只是在每次循環迭代中重復使用相同的地址/緩沖區,因此您的scanf("%s", new_element); 行每次都替換該緩沖區的內容。 然后,當您打印三個堆棧元素的內容時,每一個都將是相同的地址,您只是顯示該緩沖區的最后修改版本。

要解決此問題,請為您的“本地”變量使用std::string (然后將通過push調用復制該變量); 或者,如果您堅持使用char* ,則推送使用strdup() function 創建的副本的地址:

    for (int i=0; i<3; i++){
        char new_element[200];
        scanf("%s", new_element);
        stringLength = strlen(new_element);
        stk.push(strdup(new_element)); // Allocate and copy the buffer before pushing
    }

然后,在第二個循環中,完成后不要忘記釋放 memory:

    while(!stk.empty()){
        cout << stk.top() << " ";
        free(stk.top()); // Release the allocated memory before we lose the pointer
        stk.pop();
    }

strdup()free()函數在<stdlib.h> header 文件中聲明。

您可以使用string而不是char*

#include <iostream>
#include <stack>
#include <cstring>

int main(){
    
    stack<string> stk;
    
    int stringLength;
    
    for (int i=0; i<3; i++){
        string new_element;
        cin>>new_element;
        cout<<new_element<<"\n";
        stk.push(new_element);
    }
    
    cout << "Stack content: ";
    while(!stk.empty()){
        cout << stk.top() << " ";
        stk.pop();
    }
    cout << endl;

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM