我遇到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'
吗?
答案 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
被称为终止字符,因此您需要以某种方式跳过它。
以此为例。
因此,每当您想要跳过特殊字符时,您都希望使用两个反斜杠“\\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());