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

时间:2012-06-05 18:54:51

标签: c++ string

我有一个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

是否有更短,更有效的方法?

由于

5 个答案:

答案 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并比较效果。

同样,您可以比较strncpystd::copystd::copy_nstrcpy_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());

我更喜欢strncpystrcpy_s(以及它的旧表兄strlcpy)复制循环将在复制'\ 0'后终止,但strncpy将始终写出指定的字节数(使用'\ 0填充) '如果源字符串更短。)