如何在不通过缓冲区的情况下将字符串复制到C++中的char数组中

neu*_*cer 21 c++ string g++ char

我想将一个字符串复制到一个char数组,而不是溢出缓冲区.

因此,如果我有一个大小为5的字符数组,那么我想将一个字符串中最多5个字节复制到其中.

这样做的代码是什么?

CB *_*ley 42

这正是std::string复制功能的作用.

#include <string>
#include <iostream>

int main()
{

    char test[5];
    std::string str( "Hello, world" );

    str.copy(test, 5);

    std::cout.write(test, 5);
    std::cout.put('\n');

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果你需要null终止,你应该这样做:

str.copy(test, 4);
test[4] = '\0';
Run Code Online (Sandbox Code Playgroud)

  • 不错的解决方案,但如今并非不再没有警告:警告C4996:'std :: basic_string &lt;_Elem,_Traits,_Alloc&gt; :: copy':具有可能不安全的参数的函数调用-此调用依赖于调用方检查传递的值正确。要禁用此警告,请使用-D_SCL_SECURE_NO_WARNINGS。请参阅有关如何使用Visual C ++“检查的迭代器”的文档。 (2认同)

Jer*_*fin 21

首先,strncpy几乎肯定不是你想要的.strncpy是为了相当特定的目的而设计的.它几乎完全在标准库中,因为它已经存在,而不是因为它通常是有用的.

做你想做的最简单的方法可能就是:

sprintf(buffer, "%.4s", your_string.c_str());
Run Code Online (Sandbox Code Playgroud)

strncpy此不同,这可以保证结果将终止NUL,但如果源短于指定值,则不会在目标中填充额外数据(尽管后者在目标长度为5时不是主要问题).

  • 首选安全版本`snprintf`,它允许您指定目标缓冲区大小. (18认同)
  • @NicolBolas:这比C++ 11早,所以`snprintf`当时不是C++的一部分.即便如此,在此处指定精度会限制可写入缓冲区的数据量,从而防止缓冲区溢出(指定大于缓冲区的大小 - 如果这样做,`snprintf`将不会防止缓冲区溢出. (5认同)
  • +1代表唯一答案.但是,相对于`strncpy(buffer,str.c_str(),4),这不是很多不必要的开销; buffer [4] ='\ 0';`? (3认同)
  • @academicRobot:一般情况下,`strncpy`是更快还是更慢取决于源字符串和目标缓冲区的相对大小.由于`strncpy`在大缓冲区的情况下会浪费大量的工作,一般情况下误用`strncpy`不仅*慢**,而且*灾难性慢*,数量级更慢.在这个例子中唯一能节省一天的是不切实际的小目标缓冲区(只有5个字符). (3认同)
  • @academicRobot:您是否测试过,或者注意到其中的区别?:)我更喜欢`sprintf`解决方案,它更简单一些。只有在缺乏性能的情况下,我才会进行分析,也许会发现这是一个问题,然后使用`strncpy`对其进行测试,然后也许会发现它的效果更好。 (2认同)

AnT*_*AnT 7

使用功能 strlcpy如果您的实现提供了一个(目标网站上没有的功能),则链接断开,目标网站上找不到该材料(但该功能不在标准C库中),但它被广泛接受作为"安全"有限长度复制功能的事实上的标准名称对于零终止字符串.

如果您的实现没有提供strlcpy功能,请自己实现.例如,像这样的东西可能适合你

char *my_strlcpy(char *dst, const char *src, size_t n)
{
  assert(dst != NULL && src != NULL);

  if (n > 0)
  {
    char *pd;
    const char *ps;

    for (--n, pd = dst, ps = src; n > 0 && *ps != '\0'; --n, ++pd, ++ps)
      *pd = *ps;

    *pd = '\0';
  }

  return dst;
}
Run Code Online (Sandbox Code Playgroud)

(实际上,事实上接受了strlcpy回报size_t,因此您可能更愿意实施已接受的规范,而不是我上面所做的那样).

请注意推荐strncpy用于此目的的答案.strncpy不是一个安全的有限长度字符串复制功能,不应该用于此目的.虽然你可以强行strncpy为此目的"工作",但它仍然类似于用锤子驱动木螺钉.