1. 程式人生 > >將char* 賦值給std::string的一些陷阱

將char* 賦值給std::string的一些陷阱

這段時間,總是要使用char或者char* 賦值給std::string,踩了不少坑。於是寫了個測試程式碼,如果你不想看我的程式碼,可以跳到下面直接看總結:

#include <string>
#include <iostream>

using namespace std;


int main(int argc, char* argv[])
{
    string str1;
    cout << "str1:" << str1 << " length: " << str1.length() << " size: " << str1.size() << " capacity: " << str1.capacity() << endl;

    string str2("hello");
    cout << "str2:" << str2 << " length: " << str2.length() << " size: " << str2.size() << " capacity: " << str2.capacity() << endl;

    string str3(4, 'A');
    cout << "str3:" << str3 << " length: " << str3.length() << " size: " << str3.size() << " capacity: " << str3.capacity() << endl;

    string str4(str2);
    cout << "str4:" << str4 << " length: " << str4.length() << " size: " << str4.size() << " capacity: " << str4.capacity() << endl;

    cout << "-----------------------------------------------" << endl;

    char sz1[10] = { 0 };
    sz1[0] = 'a';
    sz1[1] = 'b';
    sz1[2] = 'c';
    char sz2[10] = { 0 };
    sz2[0] = 'a';
    sz2[3] = 'b';
    sz2[4] = 'c';

    string str5(sz1);
    string str6(sz1, 2);
    string str71(sz1, 4);
    string str72(sz1, 10);
    string str73(sz1, 30);

    cout << "str5:" << str5 << " length: " << str5.length() << " size: " << str5.size() << " capacity: " << str5.capacity() << endl;
    cout << "str6:" << str6  <<" length: " << str6.length() << " size: " << str6.size() << " capacity: " << str6.capacity() << endl;
    cout << "str71:" << str71 << " length: " << str71.length() << " size: " << str71.size() << " capacity: " << str71.capacity() << endl;
    cout << "str72:" << str72 << " length: " << str72.length() << " size: " << str72.size() << " capacity: " << str72.capacity() << endl;
    cout << "str73:" << str73 << " length: " << str73.length() << " size: " << str73.size() << " capacity: " << str73.capacity() << endl;

    cout << "-----------------------------------------------" << endl;

    string str8(sz2);
    string str9(sz2, 1);
    string str10(sz2, 2);
    string str11(sz2, 4);
    string str12(sz2, 10);

    cout << "str8:" << str8 <<" length: " << str8.length() << " size: " << str8.size() << " capacity: " << str8.capacity() << endl;
    cout << "str9:" << str9 << " length: " << str9.length() << " size: " << str9.size() << " capacity: " << str9.capacity() << endl;
    cout << "str10:" << str10 << " length: " << str10.length() << " size: " << str10.size() << " capacity: " << str10.capacity() << endl;
    cout << "str11:" << str11 << " length: " << str11.length() << " size: " << str11.size() << " capacity: " << str11.capacity() << endl;
    cout << "str12:" << str12 << " length: " << str12.length() << " size: " << str12.size() << " capacity: " << str12.capacity() << endl;

    cout << "-----------------------------------------------" << endl;

    string str13 = sz1;
    string str14 = sz2;
    cout << "str13:" << str13 << " length: " << str13.length() << " size: " << str13.size() << " capacity: " << str13.capacity() << endl;
    cout << "str14:" << str14 << " length: " << str14.length() << " size: " << str14.size() << " capacity: " << str14.capacity() << endl;

    cout << "-----------------------------------------------" << endl;

    string str15;
    str15.append(sz1);
    string str16;
    str16.append(sz1, 2);
    cout << "str15:" << str15 << " length: " << str15.length() << " size: " << str15.size() << " capacity: " << str15.capacity() << endl;
    cout << "str16:" << str16 << " length: " << str16.length() << " size: " << str16.size() << " capacity: " << str16.capacity() << endl;

    cout << "-----------------------------------------------" << endl;

    string str17;
    str17.append(sz2);
    string str18;
    str18.append(sz2, 3);
    string str19;
    str19.append(sz2, 10);
    cout << "str17:" << str17 << " length: " << str17.length() << " size: " << str17.size() << " capacity: " << str17.capacity() << endl;
    cout << "str18:" << str18 << " length: " << str18.length() << " size: " << str18.size() << " capacity: " << str18.capacity() << endl;
    cout << "str19:" << str19 << " length: " << str19.length() << " size: " << str19.size() << " capacity: " << str19.capacity() << endl;

    cout << "-----------------------------------------------" << endl;

    string str20;
    str20 += sz1;
    string str21;
    str21 += sz2;
    cout << "str20:" << str20 << " length: " << str20.length() << " size: " << str20.size() << " capacity: " << str20.capacity() << endl;
    cout << "str21:" << str21 << " length: " << str21.length() << " size: " << str21.size() << " capacity: " << str21.capacity() << endl;

    cout << "-----------------------------------------------" << endl;

    string str22;
    str22.assign(sz1);
    string str23;
    str23.assign(sz1, 9);
    string str24;
    str24.assign(sz1, 15);
    cout << "str22:" << str22 << " length: " << str22.length() << " size: " << str22.size() << " capacity: " << str22.capacity() << endl;
    cout << "str23:" << str23 << " length: " << str23.length() << " size: " << str23.size() << " capacity: " << str23.capacity() << endl;
    cout << "str24:" << str24 << " length: " << str24.length() << " size: " << str24.size() << " capacity: " << str24.capacity() << endl;

    cout << "-----------------------------------------------" << endl;

    string str25;
    str25.assign(sz2);
    string str26;
    str26.assign(sz2, 4);
    string str27;
    str27.assign(sz1, 15);
    cout << "str25:" << str25 << " length: " << str25.length() << " size: " << str25.size() << " capacity: " << str25.capacity() << endl;
    cout << "str26:" << str26 << " length: " << str26.length() << " size: " << str26.size() << " capacity: " << str26.capacity() << endl;
    cout << "str27:" << str27 << " length: " << str27.length() << " size: " << str27.size() << " capacity: " << str27.capacity() << endl;

    cout << "-----------------------------------------------" << endl;

    printf("%s\n", str26.c_str());
    printf("%s\n", str26.data());

    
    return 0;
}
輸出結果是:

現總結如下:

1. 將char*賦值給std::string如果不指定長度,則會預設以\0截斷(ASCII碼值為0);如果指定的長度超過char*字串的長度,用std::cout系列的函式輸出時,會把不屬於該char*之後的記憶體值打印出來。而對於printf系列的函式來列印std::string時遇到\0也會截斷,因而不能完全顯示。這點在列印或輸出到日誌時,這類字串時需要特別注意。

2. 如果是單個字元和一個字串賦值給std::string寫法是有區別的 —— 對於char,數目是第一個引數,對於char* 數目是第二個引數。

      例如,假定ptsr是一個字串或者字元。如果pstr是一個字串,那麼要寫成string(pstr, n),如果pstr是一個字元,那麼要寫成string(n, pstr),而此時string(pstr, n)是一個錯誤的寫法,可能會導致你的程式產生莫名其妙的問題,因為如果pstr是一個負值,負數轉換成無符號整數size_t型別,n將非常大,會導致構造字串時length非常大導致std::string構造時丟擲異常。看這兩種初始化的建構函式簽名:

 string (const char* s, size_t n);
 string(size_t n, char c);

請注意這個區別!!特別容易想當然地寫錯。如果pstr對應數值比較小的正數,可能不會產生異常,但其實程式狀態也不是你想要的。如果是負數,程式將直接產生異常。丟擲:std::length_error 。所以出現這個異常資訊,你就要好好檢查下你初始化std::string的長度資訊了。