C++如何将std::string复制到不带空终止符的char数组中

8

我正在使用一个只包含char[32]的结构体向二进制文件写入数据。基本上,我需要通过对字符串数组执行各种计算并连接结果来格式化每个数据块。我试图将std::string复制到一个没有空值终止符的char数组中。我越读越困惑了。如果我这样做:

struct block{
    char data[32];
};
block blocks[2048];
std::string buffer;

buffer = "12345678123456781234567812345678";
strcpy(blocks[0].data, buffer.c_str());

我遇到了一个错误,因为使用c_str()添加空终止符会使字符串长度变成33。如果从字符串中减去一个字符,则可以解决问题,但这样就会有空终止符,而我不想要它。我成功地执行了以下操作:

strcpy(blocks[0].data, "12345678123456781234567812345678");

但我希望先构造字符串,因为这经常涉及将来自各种数组的不同字符串连接起来。例如,我可以使用std::string来实现:

std::string buffer = stringArray1[0] + stringArray2[0];
strcpy(blocks[0].data, buffer.c_str());

但是我又遇到了空终止符的问题。我只想复制std::string中的字符,而不包括空终止符。

我正在使用VC++ 6.0。


5
您知道 VC++ 6.0 就像 IE 6 一样陈旧过时。如果您有条件更换编译器,请尽快更换。 - the_drow
感谢大家的回复。最终我使用了memcpy;之前我曾尝试过,但错误地使用了std::string.c_str而不是std::string.data。此外,我们通常使用VS2010,但这是一个需要一些旧库支持的遗留产品,这些库还没有更新以支持VS6.0之后的任何版本。 - Geo Ego
4个回答

17

你不能使用strcpy,因为它寻找NULL终止符来识别字符串的结尾,同时将NULL复制到输出字符串中。

由于你要从一个string转换成一个char缓冲区,最简单的方法是使用std::copy

#include <algorithm>

static const size_t data_size = 32;
struct block{
    char data[data_size];
};

/* ... */

std::string buffer = stringArray1[0] + stringArray2[0];
std::copy( buffer.begin(), buffer.end(), blocks[0].data );

顺便说一下,你可能可以使用一个vector<char>,而不是一个char data[32]

编辑:

另外一件事: VC6是一个古老的编译器,它在发布时就很差,当C++标准被批准时变得更糟,并且已经完全不受Microsoft支持。如果出了问题,他们甚至不会跟你谈论。你应该尽快摆脱VC6。


谢谢你的答案和建议。为了简单起见,我最终使用了memcpy,但我会在今后熟悉这些方法。 - Geo Ego

12

使用memcpy替代strcpy,这就是它存在的原因:

memcpy(blocks[0].data, buffer.data(), sizeof(blocks[0].data)); 

2
当然。我选择了memcpy,因为它最接近OP已经拥有的内容,并且他们会很舒适地使用它。如果这是你第一次遇到std::copy版本,我想你可能不会感到舒适。 - Jon
正是我所需要的。谢谢!我也会熟悉std::copy,但你说得对:我直接使用memcpy就可以了。 - Geo Ego

1

使用 strncpy() 替代 strcpy()

strncpy(blocks[0].data, buffer.c_str(), 32); 

-1

使用以下任意一行

memcpy(blocks[0].data, buffer.c_str(), buffer.size());
memcpy(blocks[0].data, buffer.c_str(), 32);
memcpy(blocks[0].data, buffer.c_str(), buffer.size() > 32 ? 32 : buffer.size());
std::copy(buffer.begin(), buffer.end(), blocks[0].data).

顺便问一下,如果字符串长度小于32个字符,你会怎么处理?你想要追加一个空字节吗?


1
不,memcpy 的第一个参数是目标地址 - 将其传递为 stringc_str() 是无用的... - Nim
2
小细节:在这里使用buffer.data()buffer.c_str()更合适(即使它不会有任何区别)。 - Jon
1
memcpy的签名是void * memcpy ( void * destination, const void * source, size_t num ),因此你的示例复制方式是错误的。 - bames53

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接