Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用嵌入的null构造std::string?_C++_Null_Stdstring - Fatal编程技术网

C++ 如何使用嵌入的null构造std::string?

C++ 如何使用嵌入的null构造std::string?,c++,null,stdstring,C++,Null,Stdstring,如果我想构造一个std::string,其行如下: std::string my_string("a\0b"); 如果我想在结果字符串中包含三个字符(a,null,b),我只得到一个。正确的语法是什么?我不知道您为什么要这样做,但请尝试以下方法: std::string my_string("a\0b", 3); 几乎所有std::strings的实现都以null结尾,所以您可能不应该这样做。请注意,“a\0b”实际上是四个字符长,因为自动空终止符(a,null,b,null)。如果您真的想

如果我想构造一个std::string,其行如下:

std::string my_string("a\0b");
如果我想在结果字符串中包含三个字符(a,null,b),我只得到一个。正确的语法是什么?

我不知道您为什么要这样做,但请尝试以下方法:

std::string my_string("a\0b", 3);

几乎所有std::strings的实现都以null结尾,所以您可能不应该这样做。请注意,“a\0b”实际上是四个字符长,因为自动空终止符(a,null,b,null)。如果您真的想这样做并打破std::string的契约,可以执行以下操作:

std::string s("aab");
s.at(1) = '\0';

但是如果你这样做了,你所有的朋友都会嘲笑你,你永远也找不到真正的幸福。

以下方法会奏效

std::string s;
s.push_back('a');
s.push_back('\0');
s.push_back('b');

如果你用C风格字符串(CARS数组)进行操作,请考虑使用< /P>

std::vector<char>
当然,您也会遇到与c字符串相同的问题。您可能会忘记空终端或写入超过分配的空间。

如果这个问题不仅仅是出于教育目的,那么最好使用std::vector。

因为C++14 我们已经能够创造

注意:C++ >代码> STD::String > <强> > < <强> >代码> 0 终止(如其他帖子中所建议的)。但是,您可以使用

C_str()
方法提取指向包含C字符串的内部缓冲区的指针

另请查看下面关于使用
向量的内容


还可以查看C++14解决方案。

我知道这个问题已经问了很久了。但是对于任何有类似问题的人来说,他们可能对下面的代码感兴趣

CComBSTR(20,"mystring1\0mystring2\0")
给出了一个优雅的答案:定义

std::string operator "" _s(const char* str, size_t n) 
{ 
    return std::string(str, n); 
}
然后可以通过以下方式创建字符串:

std::string my_string("a\0b"_s);
即便如此:

auto my_string = "a\0b"_s;
有一种“老式”方式:

然后你可以定义

std::string my_string(S("a\0b"));

你得小心点。如果将“b”替换为任何数字字符,则将使用大多数方法以静默方式创建错误的字符串。请参阅:

例如,我在程序

中间删除了这个无辜的片段。
// Create '\0' followed by '0' 40 times ;)
std::string str("\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00", 80);
std::cerr << "Entering loop.\n";
for (char & c : str) {
    std::cerr << c;
    // 'Q' is way cooler than '\0' or '0'
    c = 'Q';
}
std::cerr << "\n";
for (char & c : str) {
    std::cerr << c;
}
std::cerr << "\n";
这是我的第一个print语句,有两次,几个非打印字符,后面是换行符,后面是内存中的某个内容,我只是重写了它(然后打印出来,表明它已被覆盖)。最糟糕的是,即使是用编译,我也没有发现任何错误,通过valgrind运行程序也没有抱怨任何不正确的内存访问模式。换句话说,它完全无法被现代工具检测到

您可以通过更简单的
std::string(“0”,100)得到同样的问题,但上面的例子有点棘手,因此很难看出哪里出了问题


幸运的是,C++11使用初始值设定项列表语法为我们提供了一个很好的解决方案。这样可以避免您必须指定字符数(正如我上面所示,您可能会错误地指定字符数),并避免组合转义数
std::string str({'a','\0','b'})
对于任何字符串内容都是安全的,这与采用字符数组和大小的版本不同。

在C++14中,现在可以使用文本

using namespace std::literals::string_literals;
std::string s = "a\0b"s;
std::cout << s.size(); // 3
使用名称空间std::literals::string_literals;
std::string s=“a\0b”s;

匿名的答案很好,但C++98中也有一个非宏解决方案:

template <size_t N>
std::string RawString(const char (&ch)[N])
{
  return std::string(ch, N-1);  // Again, exclude trailing `null`
}
此外,宏还有一个问题:表达式实际上不是编写时的
std::string
,因此不能用于简单的赋值初始化:

std::string s = S("a\0b"); // ERROR!
…因此,最好使用:

#define std::string(s, sizeof s - 1)

显然,您应该在项目中只使用一种或另一种解决方案,并以您认为合适的方式调用它。

std::string不需要以NULL结尾。它不需要以NULL结尾,但在几乎所有的实现中,它都是这样,可能是因为需要c_str()访问器为您提供以null结尾的等效项。为提高效率,可以在数据缓冲区的背面保留一个null字符。但是,字符串上的任何操作(即方法)都不会使用此知识,也不会受到包含空字符的字符串的影响。空字符将以与任何其他字符完全相同的方式进行操作。这就是为什么字符串是std:-它的行为在任何平台上都没有定义的原因。我希望user595447仍然在这里,以便我可以问他们他们到底在说什么。您对此有何顾虑?您是否怀疑是否需要存储“a\0b”?或者质疑使用std::string进行此类存储?如果是后者,你有什么建议作为替代?@Constantin如果你将二进制数据存储为字符串,那么你就做错了。这就是
vector
unsigned char*
被发明的原因。我在尝试了解更多关于字符串安全性的知识时遇到了这个问题。我想测试我的代码,以确保它在从文件/网络读取预期的文本数据时,即使在中读取空字符,也能正常工作。我使用
std::string
来表示数据应该被视为纯文本,但我正在做一些散列工作,我希望确保所有内容都可以使用空字符。这似乎是对带有嵌入空字符的字符串文字的有效使用。@DuckMaestro不,这不是真的。UTF-8字符串中的
\0
字节只能是NUL。多字节编码字符永远不会包含
\0
——也不会包含任何其他ASCII字符。我在测试用例中尝试激发算法时遇到了这一点。所以有充分的理由;虽然很少。你必须使用括号而不是方括号。这个答案对于Microsoft平台来说太具体了,并且没有解决最初的问题(关于std::string的问题)。你必须小心处理这个问题。如果将“b”替换为任何数字字符,则会自动创建错误的字符串。请看:作为我准备这篇文章的一部分,我向gcc提交了一份bug报告,希望
// Create '\0' followed by '0' 40 times ;)
std::string str("\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00", 80);
std::cerr << "Entering loop.\n";
for (char & c : str) {
    std::cerr << c;
    // 'Q' is way cooler than '\0' or '0'
    c = 'Q';
}
std::cerr << "\n";
for (char & c : str) {
    std::cerr << c;
}
std::cerr << "\n";
Entering loop.
Entering loop.

vector::_M_emplace_ba
QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
using namespace std::literals::string_literals;
std::string s = "a\0b"s;
std::cout << s.size(); // 3
template <size_t N>
std::string RawString(const char (&ch)[N])
{
  return std::string(ch, N-1);  // Again, exclude trailing `null`
}
std::string my_string_t(RawString("a\0b"));
std::string my_string_m(S("a\0b"));
std::cout << "Using template: " << my_string_t << std::endl;
std::cout << "Using macro: " << my_string_m << std::endl;
std::string s = S("a\0b"); // ERROR!
#define std::string(s, sizeof s - 1)