我有一个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;
}
Run Code Online (Sandbox Code Playgroud)
是否有更短,更有效的方法?
谢谢
Ric*_*III 11
是的,使用strncpy,定义于cstring:
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';
}
Run Code Online (Sandbox Code Playgroud)
请注意,对于某些实现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;
}
Run Code Online (Sandbox Code Playgroud)
在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),那么如果您不覆盖数组中的最后一个元素,则它将以 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);
Run Code Online (Sandbox Code Playgroud)
这最多会将14 个字符复制到您的dest对象中。如果测试字符串短于14个字符,则只会复制测试字符串的长度。所有未复制的元素将保留其初始化值 (null)。