如何转换包含' \ 0'的std :: string到char *数组?

时间:2017-01-29 22:53:41

标签: c++ string char

我有一个字符串,

string str="aaa\0bbb";

我希望将此字符串的值复制到char *变量。我尝试了以下方法,但没有一个工作。

char *c=new char[7];

memcpy(c,&str[0],7);    // c="aaa"

memcpy(c,str.data(),7); // c="aaa"

strcpy(c,str.data());   // c="aaa"

str.copy(c,7);          // c="aaa"

如何在不丢失任何数据的情况下将该字符串复制到char *变量?

4 个答案:

答案 0 :(得分:1)

您可以通过以下方式执行此操作

#include <iostream>
#include <string>
#include <cstring>

int main() 
{
    std::string s( "aaa\0bbb", 7 );

    char *p = new char[s.size() + 1];

    std::memcpy( p, s.c_str(), s.size() );
    p[s.size()] = '\0';

    size_t n = std::strlen( p );

    std::cout << p << std::endl;
    std::cout << p + n + 1  << std::endl;
}

程序输出

aaa
bbb

您需要在程序中的某处保留字符数组的已分配内存大小等于s.size() + 1

如果不需要将对象的“第二部分”保留为字符串,则可以分配大小为s.size()的内存,而不是将其附加到终止零。

实际上你使用的这些方法

memcpy(c,&str[0],7);    // c="aaa"

memcpy(c,str.data(),7); // c="aaa"

str.copy(c,7);          // c="aaa"

是对的。它们只复制7个字符,前提是您不会将结果数组附加到终止零。问题是您尝试将结果字符数组输出为字符串,并且使用的运算符仅输出嵌入的零字符之前的字符。

答案 1 :(得分:0)

有两件事需要考虑:(1)确保str已经包含完整的文字(仅使用char*参数的构造函数可能会截断字符串终止符char)。 (2)如果str实际上包含完整的文字,则语句memcpy(c,str.data(),7)应该有效。唯一的问题是你如何看待&#34;结果,因为如果您将c传递给printfcout,那么一旦达到第一个字符串终止字符,它们就会停止打印。

因此:要确保将字符串文字"aaa\0bbb"完全复制到str,请使用std::string str("aaa\0bbb",7);然后,尝试在循环中打印c的内容,例如:

std::string str("aaa\0bbb",7);

const char *c = str.data();

for (int i=0; i<7; i++) {
    printf("%c", c[i] ? c[i] : '0');
}

答案 2 :(得分:0)

您的字符串由3个字符组成。您可以尝试使用

using namespace std::literals;
string str="aaa\0bbb"s;

使用\ 0创建字符串,它将包含7个字符

如果您将其用作c-string((const) char*),它仍然无法提供帮助。 c-strings不能包含零字符。

答案 3 :(得分:-1)

你已经做过(不是真的,请看下面的编辑)。但问题是,无论你使用什么来打印字符串(printf?),都使用结束字符串的c字符串约定为'\ 0'。所以它开始读取你的数据,但当它到达0时,它会认为它已经完成(因为它没有别的办法)。 如果您只想将缓冲区写入输出,则必须使用

之类的操作
write(stdout, c, 7);

现在,write有关于数据结束位置的信息,因此它可以写入所有数据。 但请注意,您的终端无法真正显示\0字符,因此它可能会显示一些奇怪的符号或根本不显示任何内容。如果你在linux上,你可以通过管道输入hexdump来查看二进制输出是什么。

编辑:

刚才意识到,你的字符串也会从const char*开始通过阅读直到零。因此,您还必须使用构造函数来告诉它读过零:

std::string("data\0afterzero", 14);

(可能有更漂亮的解决方案)