你如何构建一个的std :: string有嵌入的空?(How do you construct a

2019-09-02 03:53发布

如果我想构建一个的std :: string有这样一行:

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

我想要有结果字符串中三个字符(A,空,B),我只有一次。 什么是正确的语法?

Answer 1:

由于C ++ 14

我们已经能够创造文字std::string

#include <iostream>
#include <string>

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

    std::string s = "pl-\0-op"s;    // <- Notice the "s" at the end
                                    // This is a std::string literal not
                                    // a C-String literal.
    std::cout << s << "\n";
}

之前,C ++ 14

问题是std::string构造函数,一个const char*假设输入是一个C字符串。 C-字符串\0终止,从而解析就会停止,当它到达\0字符。

为了弥补这一点,你需要使用从构建一个char数组(不是C字符串)字符串的构造函数。 这需要两个参数 - 的指针数组和一个长度:

std::string   x("pq\0rs");   // Two characters because input assumed to be C-String
std::string   x("pq\0rs",5); // 5 Characters as the input is now a char array with 5 characters.

注意:C ++ std::string不是 \0封端的(如在其他职位的建议)。 但是,可以提取指向包含一个C-String与方法的内部缓冲器c_str()

还检查了道格T的答案低于约使用vector<char>

还检查了RIAD用于C ++ 14溶液。



Answer 2:

如果你正在做的操作就像你有一个C语言风格的字符串(字符数组)考虑使用

std::vector<char>

你有更多的自由把它当作一个数组以同样的方式,你会治疗C-字符串。 您可以使用拷贝()复制到一个字符串:

std::vector<char> vec(100)
strncpy(&vec[0], "blah blah blah", 100);
std::string vecAsStr( vec.begin(), vec.end());

你可以在许多相同的地方,你可以使用C字符串的使用

printf("%s" &vec[0])
vec[10] = '\0';
vec[11] = 'b';

当然,但是,你同样的问题C字符串吃亏。 你可能会忘记你的空终端或写入过去分配的空间。



Answer 3:

我不知道为什么你会想要做这样的事情,但试试这个:

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


Answer 4:

做用户定义的文字添加到C ++有什么新功能? 呈现优雅的答案:定义

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;

这里有一个“旧风格”的方式:

#define S(s) s, sizeof s - 1 // trailing NUL does not belong to the string

那么你可以定义

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


Answer 5:

下面的工作...

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


Answer 6:

你必须要小心这一点。 如果您有任何数字字符替换“B”,你会悄悄地创建使用大多数方法错误的字符串。 请参阅: 对于C ++字符串字面规则转义字符 。

例如,我在节目中间掉了这个无辜的看着片段

// 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

那是我第一次打印语句两次,几个非打印字符,跟着一个换行符,其次是一些在内部存储器,这是我刚刚改写(再印,表明它已被覆盖)。 最糟糕的是,即使有编制这彻底和详细的GCC警告没有给我任何东西显示自己的错误,并通过Valgrind的运行程序没有抱怨任何不正确的内存访问模式。 换句话说,它是由现代工具完全感觉不到的。

你可以用更简单的得到同样的问题std::string("0", 100); ,但上面的例子是有点麻烦,因此很难看到什么是错的。

幸运的是,C ++ 11为我们提供了一个很好的解决方案,以使用初始化列表语法问题。 这样您就不必指定字符(如我上面显示,你可以做不正确地)的数量,并避免结合逃脱号码。 std::string str({'a', '\0', 'b'})为任何字符串内容安全的,不同于采取的阵列版本char和尺寸。



Answer 7:

在C ++ 14你现在可以使用文字

using namespace std::literals::string_literals;
std::string s = "a\0b"s;
std::cout << s.size(); // 3


Answer 8:

最好使用std ::矢量<字符>,如果这个问题不只是教育目的。



Answer 9:

化名的回答是优秀的,但有在C ++ 98以及一个非宏溶液:

template <size_t N>
std::string RawString(const char (&ch)[N])
{
  return std::string(ch, N-1);  // Again, exclude trailing `null`
}

使用此功能, RawString(/* literal */)将产生相同的字符串作为S(/* literal */)

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如写的,因此不能用于例如简单的赋值初始化:

std::string s = S("a\0b"); // ERROR!

...所以它可能是最好的使用方法:

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

显然,你应该只使用一个或项目中的其他解决方案,并调用它任何你认为合适。



Answer 10:

我知道这是一个很长一段时间这个问题已经被问。 但对于谁是有一个类似的问题的人可能会喜欢下面的代码。

CComBSTR(20,"mystring1\0mystring2\0")


Answer 11:

性病的几乎所有的实现::字符串都是空终止的,所以你可能不应该这样做。 需要注意的是“A \ 0B”,实际上是因为自动空终止(一,空,B,空)的四个字符长。 如果你真的想这样做,打破的std :: string的合同,你可以这样做:

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

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



文章来源: How do you construct a std::string with an embedded null?