搜尋

首頁  >  問答  >  主體

c++ 自带string类 的对象 字符串结尾带不带‘\0’?

c++ 自带string类 的对象 字符串结尾带不带‘0’?

黄舟黄舟2810 天前817

全部回覆(6)我來回復

  • 大家讲道理

    大家讲道理2017-04-17 13:46:57


    先上圖

    string 類型把' 0'當做普通字符處理,長度加一,可見' 0'不是結束字符,不含有特殊功能,string末尾不需加' 0'

    C語言中沒有string類型,而是用字元陣列代替,一般字元陣列可以不確定長度
    char * string = " ABCD" ,編譯器靠什麼知道字串結束,一般在後面加' 0 '

    回覆
    0
  • 高洛峰

    高洛峰2017-04-17 13:46:57

    C++ 中的std::string和 C-style string 是兩種不同的字串,前者是標準函式庫中定義的一個類,後者是字元陣列的別名。

    • C-style string:通常以作為結尾。

    • std::string:標準中未規定需要作為字串結尾。編譯器在實作時既可以在結尾加上,也可以不加。但是,當透過c_str()data()(二者在C++11 及以後是等價的)來把std::string轉換為const char *時,會發現最後一個字符是(原因見文末附錄)。


    C-style string 中一般不能包含字符(因為這個字符被當作表示字符串結束的特殊字符處理了),如果包含這個字符,那麼其後的字符將會被忽略。即:

    char s[] = "ab
    std::string s{'a', 'b', '
    template< 
        class CharT, 
        class Traits = std::char_traits<CharT>, 
        class Allocator = std::allocator<CharT>
    > class basic_string;
    ', 'c'}; //std::string s = "ab
    string s{'a', 'b', 'rrreee', 'c'};
    cout << s.size() << endl;  // 输出 4
    s += 'rrreee';
    s += 'd';
    cout << s.size() << endl;  // 输出 6
    c"; // 这里由于是从 C-style string 构造 std::string,所以仍然会忽略 rrreee 之后的字符 cout << s << endl; // 输出 ab c
    c"; cout << s << endl; // 输出 ab

    std::string沒有這個限制。即:

    rrreee

    附錄

    透過c_str()data()(二者在 C++11 及以後是等價的)來把std::string轉換為const char *時,會發現最後一個字元是。想理解這個問題需要一點背景知識:

    一,std::stringstd::basic_string<CharT, Traits, Allocator>這個模板的特例std::basic_string<char>。即模板:

    rrreee

    中的參數CharTchar時的特例。

    二,s.size()會回傳std::string中字元的個數,即:

    rrreee

    三,使用[]運算子(即std::basic_string::reference std::basic_string::operator[](size_type pos);)取得std::string中的字元時,其字元的範圍pos是從0size()。其中0size()-1是所儲存的字符,而對於pos == size()有以下規定:

    If pos == size(), a reference to the character with value CharT() (the null character) is returned. For the first (non-const) modion, the behavior is undefined if this ifieder

    意思是當存取

    時,會回傳s[s.size()]的回傳值的引用,而CharT()對於CharTstd::string,且char回傳的是char(),所以00會回傳s[s.size()]

    四,透過

    c_str()data())傳回的指標存取字串時,其效果為:const CharT* c_str() const;

    Returns: A pointer

    such that p for each p + i == &operator[](i) in [i,0].size()

    p[s.size()]等價於p + s.size()等價於&s.operator[](s.size())等價於s[s.size()],所以會發現回傳值是

    回覆
    0
  • PHP中文网

    PHP中文网2017-04-17 13:46:57

    0是C語言中的字元陣列作為結束標記用的,C++字串沒有這個需要

    回覆
    0
  • 巴扎黑

    巴扎黑2017-04-17 13:46:57

    何不建立string對象,列印看看他的size?

    回覆
    0
  • 巴扎黑

    巴扎黑2017-04-17 13:46:57

    c語言用char*指標當字串時,在讀取字串時需要一個特殊字元0來標記指標的結束位置,也就是通常認為的字串結束標記。
    而c++語言則是物件導向的,長度資訊直接被儲存在了物件的成員中,讀取字串可以直接根據這個長度來讀取,所以就沒必要需要結束標記了。而且結束標記也不利於讀取字串中夾雜0字元的字串。

    参照std::string的实现 bits/basic_string.h

    回覆
    0
  • 大家讲道理

    大家讲道理2017-04-17 13:46:57

    String本身是封裝過的,會把'

    #include <iostream>
    #include <stdio.h>
    #include <string>
    using std::string;
    using namespace std;
    
    
    void test1(){
        string s1 = "Hello";
        const char * v1 = s1.data();
        printf("0x%.2x\n", v1[s1.size()]);
    
        string *s2 = new string("Hello");
        const char * v2 = s2->data();
        printf("0x%.2x\n", v2[s2->size()]);
    
    }
    
    void test2(){
        string s1 = "Hello";
        const char * v1 = s1.c_str();
        printf("0x%.2x\n", v1[s1.size()]);
    
        string *s2 = new string("Hello");
        const char * v2 = s2->c_str();
        printf("0x%.2x\n", v2[s2->size()]);;
    }
    
    int main()
    {
        test1();
        test2();
        return 0;
    }
    

    輸出都是0x00

    回覆
    0
  • 取消回覆