std :: string在\ 0处停止

时间:2017-03-18 12:58:25

标签: c++ string

我遇到std::string ..

的问题

问题是'\0'被识别为字符串的结尾,就像在类似C的字符串中一样。

例如以下代码:

#include <iostream>
#include <string>

int main ()
{
    std::string s ("String!\0 This is a string too!");
    std::cout << s.length(); // same result as with s.size()
    std::cout << std::endl << s;

    return 0;
}

输出:

7
String!

这是什么问题? std::string不应该像其他任何角色一样对待'\0'吗?

8 个答案:

答案 0 :(得分:8)

考虑一下:如果给你const char*,你将如何确定,真正的终止0在哪里,以及在哪里嵌入一个?

你需要明确地传递一个字符串大小,或者从两个迭代器(指针?)构造字符串

#include <string>
#include <iostream>


int main()
{
    auto& str = "String!\0 This is a string too!";
    std::string s(std::begin(str), std::end(str));
    std::cout << s.size() << '\n' << s << '\n';
}

示例:http://coliru.stacked-crooked.com/a/d42211b7199d458d

编辑:@ Rakete1111让我想起了字符串文字:

using namespace std::literals::string_literals;
auto str = "String!\0 This is a string too!"s;

答案 1 :(得分:4)

您的std::string实际上只有7个字符和终止'\0',因为这是您构建它的方式。查看list of std::basic_string constructors:没有能够记住字符串文字大小的数组版本。在这里工作的是这一个:

basic_string( const CharT* s,
              const Allocator& alloc = Allocator() );

"String!\0 This is a string too!" char const[]数组将转换为指向第一个char元素的指针。该指针传递给构造函数,并且是它拥有的所有信息。为了确定字符串的大小,构造函数必须递增指针,直到它找到第一个'\0'。而这恰好是数组内部的一个。

如果你碰巧在字符串中使用了很多零字节,那么std::vector<char>甚至std::vector<unsigned char>可能是解决问题的更自然的方法。

答案 2 :(得分:1)

\0被称为终止字符,因此您需要以某种方式跳过它。

String represntation

以此为例。

因此,每当您想要跳过特殊字符时,您都希望使用两个反斜杠“\\0

'\\0'是一个双字符的字面值

   std::string test = "Test\\0 Test"

结果:

   Test\0 Test

大多数初学者在装载时也会犯错误。文件:

 std::ifstream some_file("\new_dir\test.txt"); //Wrong
 //You should be using it like this : 
 std::ifstream some_file("\\new_dir\\test.txt"); //Correct

答案 3 :(得分:0)

您正在从字符串文字构建std::string。字符串文字自动以'\0'终止。因此,字符串文字"f\0o"被编码为以下字符数组:

{'f', '\0', 'o', '\0'}

将调用string char const*构造函数,并将实现如下:

string(char const* s) {
    auto e = s;
    while (*e != '\0') ++e;

    m_length = e - s;
    m_data = new char[m_length + 1];
    memcpy(m_data, s, m_length + 1);
}

显然,这不是技术上正确的实现,但你明白了。您手动插入的'\0'将被解释为字符串文字的结尾。

如果您想忽略额外的'\0',可以使用std::string字面值:

#include <iostream>
#include <string>

int main ()
{
    using namespace std::string_literals;

    std::string s("String!\0 This is a string too!"s);
    std::cout << s.length(); // same result as with s.size()
    std::cout << std::endl << s;

    return 0;
}

输出:

30
String! This is a string too!

答案 4 :(得分:0)

简而言之,您正在从标准C字符串构造C ++字符串。

标准C字符串是零终止的。因此,您的C字符串参数将在它可以找到的第一个\0字符中终止。该字符是您在字符串"String!\0 This is a string too!"

中明确提供的字符

而不是编译器在C标准字符串末尾隐式自动提供的第二个。

答案 5 :(得分:-1)

逃离你的\ 0

std::string s ("String!\\0 This is a string too!");

你会得到你需要的东西:

31
String!\0 This is a string too!

答案 6 :(得分:-1)

这不是问题,这是预期的行为。

也许你可以详细说明为什么你的字符串中有\ 0。

使用std :: vector可以在字符串中使用\。

答案 7 :(得分:-1)

找到零的索引,然后擦除:

  auto index = str.find('\0');
  str.erase(str.begin() + index, str.end());