C++ 将 std::string 复制到没有空终止的 char 数组

Posted

技术标签:

【中文标题】C++ 将 std::string 复制到没有空终止的 char 数组【英文标题】:C++ copy std::string to char array with no null termination 【发布时间】:2012-01-10 20:24:35 【问题描述】:

我正在使用仅包含 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。

【问题讨论】:

你知道 VC++ 6.0 就像 IE 6 一样。可怕。如果您能够切换编译器,请快速切换。 谢谢大家的回复。我最终使用了 memcpy;我之前曾尝试过,错误地使用 std::string.c_str 而不是 std::string.data。此外,我们通常使用 VS2010,但这是一个遗留产品,需要一些尚未更新的旧库以支持 VS6.0 之后的任何内容。 【参考方案1】:

使用memcpy 而不是strcpy,这就是它的用途:

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

【讨论】:

@AlfP.Steinbach:当然。我选择了memcpy,因为它最接近 OP 已有的,而且他们会很舒服地使用它。我想std::copy 版本如果你是第一次遇到它,我想就不能这么说。 正是我需要的。谢谢!我也将熟悉 std::copy ,但你说得对:我把 memcpy 猛击进去,它起作用了。【参考方案2】:

您不能使用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&lt;char&gt;,而不是char data[32]

编辑:

顺便说一句:VC6 是一个古老的编译器,它刚出来时很糟糕,在 C++ 标准被批准时很糟糕,并且完全不受 Microsoft 的支持。如果出了什么问题,他们甚至不会和你说话。你应该尽快下VC6。

【讨论】:

感谢您的回答和建议。为简单起见,我最终使用了 memcpy,但我将在以后熟悉这些方法。【参考方案3】:

使用下面的行之一

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 个字符时,你会处理这种情况吗?那你要追加一个空字节吗?

【讨论】:

不,memcpy 接受目标作为第一个参数 - 传递 c_str()string 是没用的...... 次要 nitpick:buffer.data() 在这里比buffer.c_str() 更合适(尽管它不会产生影响)。 memcpy 的签名是 void * memcpy ( void * destination, const void * source, size_t num ) 所以你的例子是复制错误的方式。【参考方案4】:

使用strncpy() 代替strcpy()

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

【讨论】:

以上是关于C++ 将 std::string 复制到没有空终止的 char 数组的主要内容,如果未能解决你的问题,请参考以下文章

c++,为啥要使用 const std::string & parameterName? [复制]

如何在 C++ 中将整个文件读入 std::string?

如何使用参数将 std::string 复制到 std::string?

从无符号字符到 std::string 的 C++ 转换 [重复]

在 C++ 中定义 std::string 没有转义字符

如何将std :: string复制到unsigned char数组?