【问题标题】:STL basic_string length with null characters带有空字符的 STL basic_string 长度
【发布时间】:2011-07-16 05:29:03
【问题描述】:

为什么你可以在 std::basic_string 中插入一个 '\0' 字符并且 .length() 方法不受影响但是如果你调用 char_traits<char>::length(str.c_str()) 你会得到字符串的长度直到第一个 ' \0' 字符?

例如

string str("abcdefgh");
cout << str.length(); // 8
str[4] = '\0';
cout << str.length(); // 8
cout << char_traits<char>::length(str.c_str()); // 4

【问题讨论】:

    标签: c++ string stl stdstring


    【解决方案1】:

    好问题!

    原因是 C 风格的字符串被定义为以空字节结尾的字节序列。当您使用 .c_str() 从 C++ std::string 中获取 C 样式字符串时,您将返回 C++ 字符串存储的序列,其后有一个空字节。当你将它传递给strlen 时,它会扫描字节,直到找到一个空字节,然后报告它在此之前找到了多少个字符。如果string 包含一个空字节,那么strlen 将报告一个小于整个字符串长度的值,因为它会在到达字符串的真正结尾之前停止。

    一个重要的细节是strlenchar_traits&lt;char&gt;::length 不是同一个函数。但是,char_traits&lt;charT&gt;::length 的 C++ ISO 规范(第 21.1.1 节)说 char_traits&lt;charT&gt;::length(s) 返回 smallest i 使得 char_traits&lt;charT&gt;::eq(s[i], charT()) 为真。对于char_traits&lt;char&gt;eq 函数通过进行== 比较仅返回两个字符是否相等,并通过写入char() 构造一个字符产生一个空字节,因此这等于说“哪里是字符串中的第一个空字节?”这基本上就是 strlen 的工作原理,尽管两者在技术上是不同的功能。

    一个 C++ std::string,然而,它是“任意字符序列”的更一般的概念。它的实现细节对外界是隐藏的,尽管它可能由开始和停止指针或指针和长度表示。因为这种表示不依赖于存储的字符,所以询问std::string 的长度会告诉您其中有多少字符,而不管这些字符实际上是什么。

    希望这会有所帮助!

    【讨论】:

    • +1,我想补充一点,如果你真的想要内部空字节,我相信可以使用basic_string&lt;&gt;::data()成员函数。
    • @dappawit- 不是c_str() 取出空字节而data() 将它们留在里面;相反,它们都有空字节,c_str() 保证最后有一个空字节,data 没有。问题是字符串内部的那些字节如何被用于 C 风格字符串实现的函数解释。
    • 啊哈!您添加了我将要回答的部分。
    • 这让我想到了下一个问题,如果字符串类似乎甚至没有使用 Character Traits 的意义何在? (这里不要回答)
    • @MattSmith-请参阅我对您其他问题的(长)回答。简短的版本是 std::string 确实使用了 traits 类,这给了你难以置信的灵活性。
    猜你喜欢
    • 2013-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多