Как преобразовать вектор строки STL в char * элегантным / быстрым способом? - PullRequest
1 голос
/ 11 августа 2011

Это делится на более мелкие этапы:

  1. Как рассчитать общую длину всех строк в векторе?
  2. Выделите char * mem space
  3. Скопируйте векторные строки в это пространство

Есть ли быстрый элегантный способ сделать это?

Ответы [ 4 ]

7 голосов
/ 11 августа 2011

Самый элегантный, но, возможно, не самый быстрый способ, о котором я могу подумать, будет следующим:

std::string s = std::accumulate(v.begin(), v.end(), std::string());
char * c = new char[s.size() + 1];
std::strcpy(c,s.c_str());

Хотя я сам не фанат голого динамического распределения и лично никогда бы не использовал его, я оставлю это для вас.

Если вам нужно добавить разделитель пробела между элементами, он станет немного сложнее, и я бы, вероятно, использовал другое решение, например:

std::ostringstream oss;
std::copy(v.begin(), v.end(), std::ostream_iterator<std::string>(oss," "));
size_t sz = oss.str().size();
if(sz) --sz; // truncate trailing space if there is one
char * c = new char[sz+1];
std::copy_n(oss.str().c_str(), sz, c);
c[sz] = 0;
5 голосов
/ 11 августа 2011

Вот реализация C ++ 0x:

#include <cstddef>
#include <algorithm>
#include <numeric>
#include <string>
#include <vector>

std::vector<char> concat_strings(std::vector<std::string> const& vecs)
{
    std::size_t const cumulative_length = std::accumulate(
        vecs.begin(),
        vecs.end(),
        static_cast<std::size_t>(0),
        [](std::size_t const acc, std::string const& str)
        {
            return acc + str.size();
        }
    );

    std::vector<char> ret;
    ret.reserve(cumulative_length);

    std::for_each(
        vecs.begin(),
        vecs.end(),
        [&ret](std::string const& str)
        {
            ret.insert(ret.end(), str.begin(), str.end());
        }
    );

    return ret;
}

Полученный std::vector<char> - это ваш эффективный char*.

Для C ++ 03 это будет во многом таким же,но вам понадобятся правильные функторы вместо лямбд (или используйте лямбда-библиотеку C ++ 03, например Boost . Phoenix ).

1 голос
/ 11 августа 2011

Это не элегантное требование, поэтому я не могу придумать элегантного решения.

непроверенный код

vector<string> vec = ...;
size_t total_size = 0;
for (size_t i = 0; i < vec.size(); ++i)
  total_size += vec[i].size();
char* mem = new char[total_size];
char* p = mem;
for (size_t i = 0; i < vec.size(); ++i)
{
  memcpy(p, vec[i].data(), vec[i].size());
  p += vec[i].size();
}
0 голосов
/ 11 августа 2011

Вот путь STL:

#include <algorithm>  // std::copy
#include <iostream>   // std::cout
#include <iterator>   // std::ostream_iterator
#include <sstream>    // std::ostring_stream
#include <string>     // std::string
#include <vector>     // std::Vector

using namespace std;

typedef std::vector<std::string> string_vector;

int main( int argc, char ** argv )
{
  string_vector v;
  v.push_back("string 1, ");
  v.push_back("string 2, ");
  v.push_back("string 3");

  std::ostringstream os;
  std::copy( v.begin(), v.end(), std::ostream_iterator<std::string>( os, "" ) );
  std::string result = os.str();

  std::cout << "result: " << result << std::endl;

  return 0;
}

Выход:

result: string 1, string 2, string 3
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...