如何将std :: vector <const char * =“”>复制到void *?</const>中

时间:2014-10-04 16:48:19

标签: c++

我有一个完全用字符串启动的std::vector<const char*> v向量。如何将其复制到已初始化的void*

int main() {
 std::vector<const char*> v;
 v.push_back("abc");
 v.push_back("def"); 
 void* b = malloc(6);

 // how to copy v in to b?
}

谢谢

5 个答案:

答案 0 :(得分:3)

您可以使用基于范围的语句。例如

void *p = b;
for ( const char *s : v )
{
   size_t n = std::strlen( s );
   std::memcpy( p, s, n );
   p = ( char * )p + n;
}

使用标头std::accumulate

中声明的标准算法<numeric>也可以这样做

例如

#include <iostream>
#include <vector>
#include <numeric>
#include <cstring>

int main() 
{
    std::vector<const char*> v;

    v.push_back( "abc" );
    v.push_back( "def" ); 
    void *b = new char[6];  

    auto p = std::accumulate( v.begin(), v.end(), b,
                              []( void *acc, const char *s ) -> void *
                              {
                                  size_t n = std::strlen( s );
                                  return ( ( char * )std::memcpy( acc, s, n ) + n );
                              } );

    std::cout.write( (const char * )b , ( const char * )p - ( const char * )b );
    std::cout << std::endl;

    return 0;
}

输出

abcdef

考虑到编写

会更好
void* b = new char[6];

答案 1 :(得分:0)

遍历向量,每次都按指针移动指针。

答案 2 :(得分:0)

int currentIndex = 0;
for(int i = 0; i < v.length(); i++) {
    memcpy(b + currentIndex, v[i], strlen(v[i]));
    currentIndex += strlen(v[i]);
}

这样的事情,可能行不通,我没有测试过。

如果您想将b用作字符串,则需要在结尾添加0

答案 3 :(得分:0)

试试这个:

 std::vector<const char*> v;
 v.push_back("abc");
 v.push_back("def"); 
 void* b = malloc(6);
int l = strlen(v[0]);
memcpy(b, v[0], l);
l = strlen(v[1]);
memcpy(b+l, v[1], l); 

答案 4 :(得分:0)

这是我能想到的最像C ++的方式。它不使用任何C风格的字符串操作或内存管理功能,它尽可能安全。缺点是在没有实际需要的情况下分配和释放临时缓冲区。

此示例中使用了以下标头。

#include <cstddef>
#include <iostream>
#include <memory>
#include <string>
#include <vector>

现在,第一个版本(我更喜欢)分配一个正确大小的缓冲区,并将其包装在std::unique_ptr<char[]>中,然后调用者可以从中提取缓冲区并隐式地将其转换为void *如果需要的话。

std::unique_ptr<char[]>
concatenate(const std::vector<const char *>& words)
{
  std::string buffer {};
  std::unique_ptr<char[]> dup_uptr {};
  for (const auto word : words)
    buffer += word;
  dup_uptr.reset(new char[buffer.size() + 1]);
  buffer.copy(dup_uptr.get(), buffer.size());
  dup_uptr.get()[buffer.size()] = '\0';
  return dup_uptr;
}

第二个版本将目标缓冲区及其大小作为参数,并在那里复制连接的字符串。如果缓冲区太小而且安全性也很低,这显然会失败,因为我们可能会犯错误并传递错误的缓冲区大小。为方便起见,它会返回一个指向字符串的char *指针,如果缓冲区太小则返回nullptr

char *
concatenate(const std::vector<const char *>& words,
            void *const dest,
            const std::size_t size)
{
  char * dest_chars = static_cast<char *>(dest);
  std::string buffer {};
  for (const auto word : words)
    buffer += word;
  // If we cannot copy the whole thing, copy nothing at all.
  if (buffer.size() >= size)
    return nullptr;
  buffer.copy(dest_chars, buffer.size());
  dest_chars[buffer.size()] = '\0';
  return dest_chars;
}

这两个功能可以这样使用:

int
main()
{
  const std::vector<const char*> vec {"abc", "def"};
  // first version
  {
    auto concat = concatenate(vec);
    std::cout << concat.get() << std::endl;
  }
  // second version
  {
    auto tempbuff = std::get_temporary_buffer<void>(100);
    if (auto concat = concatenate(vec, tempbuff.first, tempbuff.second))
      std::cout << concat << std::endl;
    std::return_temporary_buffer(tempbuff.first);
  }
  return 0;
}