繁体   English   中英

从std :: string复制到char数组并以null结尾结果

[英]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并比较性能。

同样,你可以比较strncpystd::copystd::copy_nstrcpy_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM