簡體   English   中英

嘗試使用 strtok 時調用構造函數

[英]Constructor being called when trying to use strtok

我編寫了一個名為 DSString 的自定義字符串類,其中包含一個私有成員 char* 數據。 我正在嘗試解析 csv 文件中的行,將在文件行中找到的每個單詞添加到 std::set 的 DSString 對象。 我調用 getline 將文件中的一行讀入 char* 緩沖區,然后調用 strtok 獲取單詞。 但是,下面的while循環不起作用; 我的調試器告訴我,在到達那行代碼時,它使用參數 NULL 調用 DSString.h 中的構造函數,然后程序結束。

int main (int argc, char ** argv) {
    
    ifstream input;
    input.open(argv1);

    int reviewLinesCtr = 0;
    char line[16000];

    set <DSString>positiveWordSet;

    while (input.getline(line,16000)) {
        if (reviewLinesCtr == 10) break;

            //Push review to positive set
            DSString word = strtok(line, " ");
            while (word != nullptr) {         //Program ends abruptly here
                positiveWordSet.insert(word);
                word = strtok(nullptr, " ");
            }
        }
        reviewLinesCtr++;
    }

    return 0;
}

DSString 只有私有成員char *dataint size 這是 DSString 中的相關代碼:

    DSString::DSString(const char* param) {  //This is the constructor being  passed, param = NULL, which crashes the program.
        data = new char[strlen(param) + 1];
        this->size = strlen(param) + 1;
        strcpy(data, param);
    }

    DSString& DSString::operator= (const char* source)  {
        if (data != nullptr) {
            delete[] data;
        }
        data = new char[strlen(source + 1)];
        size = strlen(source) + 1;
        strcpy(data, source);
        return *this;
    }

    bool DSString::operator!= (const DSString& rhs) const {
        if (strcmp(this->data, rhs.data) != 0) {
            return true;
        }
        else {
            return false;
        }
    } 

這是大學項目的一部分,因此我們需要實現自定義 DSString 類。 否則我不會使用它,而是使用 std::string。 除了要從文件中讀取的緩沖區外,我們也不能在程序中的任何地方使用 char*。 當我嘗試開始執行此 while 循環時,為什么會調用此構造函數並將其指定為 NULL 作為參數? 我該如何解決?

如果這是一個重復的問題,我深表歉意,我已經在互聯網上搜索了一段時間,但沒有找到任何有助於解釋這里發生的事情的信息。 任何幫助,將不勝感激。

崩潰的原因很可能在 eeorika 的回答中有所概述。 沒有必要在這里重復。

為什么調用構造函數:

DSString word = strtok(line, " ");

Copy Initialization ,因此調用的是構造函數,而不是賦值運算符。

旁注:

還有一個致命的錯誤。 由於strtok在沒有更多標記時返回nullptr如果沒有更多標記,將DSString::DSString(const char* param)並且

data = new char[strlen(param) + 1];

將在空指針上調用strlen 卡布姆

解決方案:在const char *變量中捕獲strtok的返回值並測試它是否為nullptr 只有在有令牌時才繼續構建。

由於分配要求是您不能使用char *變量,因此請確認您是否可以使用const char * 如果沒有,那是一種有趣(而且非常愚蠢)的泡菜。

賦值運算符泄漏內存。

DSString& DSString::operator= (const char* source)  {
    delete[] data; // must release the object's current string
                   // before allocating a new one
    data = new char[strlen(source + 1)]; 
    size = strlen(source) + 1;
    strcpy(data, source);
    return *this;
}
DSString word = .... while (word != nullptr) { //Program ends abruptly here

在這里,您將DSString對象與nullptr進行比較。 讓我們看看操作符過載:

 bool DSString::operator!= (const DSString& rhs) const {

它接受一個DSString引用,而不是一個指針。 但是,您的類可以從指針隱式轉換,因此可以從std::nullptr_t間接轉換,因為它有一個轉換構造函數:

 SString::DSString(const char* param) { //This is the constructor being passed, param = NULL, which crashes the program.

由於構造函數調用strlen(param)strcpy(data, param); ,將 null 傳遞給該構造函數具有未定義的行為。

為避免使用隱式轉換意外調用此構造explicit ,您應該將其聲明為explicit

將 null 傳遞給構造函數在這里也是一個問題: DSString word = strtok(line, " "); .

要修復邏輯,您應該使用帶有strtok的指針,並且只有在您檢查它是非空后才創建您的字符串:

        char* word = strtok(line, " ");

除了要從文件中讀取的緩沖區外,我們也不能在程序中的任何地方使用 char*。

坦率地說,使用strtok而不是使用char*只是愚蠢的要求。

好像你已經違反了這個要求:

DSString只有私有成員char *data和 ...

無論如何,如果您需要遵循此類限制,則需要更改構造函數以在傳入 null 時正確運行。 具體來說,在這種情況下,它可能不會將該指針傳遞給具有未定義行為的函數。

並且,如果您將成員設置為空,那么您還必須在將其傳遞給上述此類函數之前檢查該成員是否為空。

暫無
暫無

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

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