[英]Copying non null-terminated unsigned char array to std::string
[英]copying from a std::string to a char array and null-terminating the result
我有一个Visual Studio 2008 C ++ 03应用程序,我想从std :: string复制到char数组,但我需要将char数组空终止,即使它必须截断字符串才能这样做。
例如,这可以按预期工作:
inline void CopyAndNullTerminate( const std::string& source,
char* dest,
size_t dest_size )
{
source.copy( dest, dest_size );
using std::min;
char* end = dest + min( dest_size - 1, source.size() );
*end = '\0';
}
int main()
{
enum{ MAX_STRING_SIZE = 15 };
char dest[ MAX_STRING_SIZE ];
std::string test = "This is a test";
CopyAndNullTerminate( test, dest, MAX_STRING_SIZE );
assert( strcmp( test.c_str(), dest ) == 0 );
return 0;
}
例如: http : //ideone.com/0EBYb
是否有更短,更有效的方法?
谢谢
是的,使用在cstring
定义的strncpy
:
void copyString(const std::string& input, char *dst, size_t dst_size)
{
strncpy(dst, input.c_str(), dst_size - 1);
dst[dst_size - 1] = '\0';
}
请注意,对于std::string
某些实现(如@ K-ballo所指出的),这可能更短,但效率更低。 这是因为std::string
不能保证使用C-syle字符串实现,尽管对于大多数情况可能就是这种情况。
假设dest_size
保证至少为1(这对我来说似乎是合理的,否则无法复制并将null终止到缓冲区中):
inline void CopyAndNullTerminate( const std::string& source,
char* dest,
size_t dest_size )
{
dest[source.copy(dest, dest_size-1)] = 0;
}
在C ++ 11和所有主动维护的C ++ 03实现(包括Visual Studio)中, std::string
具有连续存储,就像std::vector
。 因此,您可以使用memcpy
而不是std::string::copy
并比较性能。
同样,你可以比较strncpy
, std::copy
, std::copy_n
, strcpy_s
,以及我可能忘记的其他人,看看哪个是最优化的。 在每种情况下,您都可以计算要复制的字节数为std::min(source.size(), dest_size-1)
。 这也避免了strncpy
情况(将一个小字符串复制到一个大缓冲区)。
当完成所有这些,你可以依靠的事实,它是有效的调用source[0]
即使source
是一个空字符串。
如果首先初始化目标字符串(为null),那么如果不覆盖数组中的最后一个元素,则可以使其终止。
enum{ MAX_STRING_SIZE = 15 };
char dest[ MAX_STRING_SIZE ] = {0}; // all elements are initialized to 0
std::string test = "This is a test";
// determine the length to copy, it will be the min of MAX_STRING_SIZE-1
// or test.size. This will ensure that even if the string it shorter than
// the MAX_STRING_SIZE, that it will copy properly -- without reading past the
// array bounds of the string.
auto copy_len = std::min(test.size(), MAX_STRING_SIZE - 1);
std::copy(
test.begin(),
test.begin() + copy_len,
dest);
这将最多 14个字符复制到您的dest
对象。 如果测试字符串短于14个字符,则只复制测试字符串的长度。 未复制的所有元素将保持其初始值(null)。
这是一对较短的一对:
inline void CopyAndNullTerminate( const std::string& source,
char* dest,
size_t dest_size )
{
*dest = '\0'; // assumes `dest_size > 0`
strncat(dest, source, dest_size);
}
void CopyAndNullTerminate(std::string const &source,
char *dest,
size_t dest_size) {
sprintf(dest, "%*s", dest_size, source.c_str());
}
效率可能会有更多的问题,但我认为没有任何理由相信要么特别慢。
好的'C strcpy_s怎么样?
strcpy_s(dest, MAX_STRING_SIZE, test.c_str());
我更喜欢这个strncpy
。 strcpy_s
(及其较旧的表兄strlcpy
)复制循环将在复制'\\ 0'后终止,但strncpy
将始终写出指定的字节数(如果源字符串较短,则使用'\\ 0'填充)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.