我有一个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;
}
是否有更短,更有效的方法?
由于
答案 0 :(得分:10)
是的,请使用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字符串来实现,尽管在大多数情况下可能就是这种情况。
答案 1 :(得分:9)
假设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
这一事实。
答案 2 :(得分:4)
如果首先初始化目标字符串(为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)。
答案 3 :(得分:2)
以下是一对较短的一对:
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());
}
效率可能会有更多问题,但我认为没有理由相信要么特别慢。
答案 4 :(得分:1)
好的'C strcpy_s怎么样?
strcpy_s(dest, MAX_STRING_SIZE, test.c_str());
我更喜欢strncpy
。 strcpy_s
(以及它的旧表兄strlcpy
)复制循环将在复制'\ 0'后终止,但strncpy
将始终写出指定的字节数(使用'\ 0填充) '如果源字符串更短。)