Как скопировать определенное количество символов из файла в вектор STL-способом? - PullRequest
6 голосов
/ 30 сентября 2010

Если я хочу скопировать содержимое файла в вектор, я могу сделать это так:

std::ifstream file("path_to_file");
std::vector<char> buffer(std::istream_iterator<char>(file), 
                         std::istream_iterator<char>());

Мой вопрос: как бы я это сделал, если хочу скопировать только первые n символы?

Редактировать Я мог бы написать свою собственную версию copy, но есть ли способ сделать это, используя только существующие компоненты?

Ответы [ 5 ]

8 голосов
/ 30 сентября 2010

Как указывает Александр, самый быстрый путь будет

std::vector<char> buffer(n);
file.read(&buffer[0], n);

В C ++ 0x вы можете использовать buffer.data() вместо &buffer[0]; последний имеет неопределенное поведение, если n == 0.

6 голосов
/ 30 сентября 2010

Как отметил Стив , для этого потребуется copy_n(), которого из-за недосмотра нет в текущей стандартной библиотеке, но он будет в C + + 1x. Вы можете легко реализовать его самостоятельно, вот один, который я считаю правильным:

template<class InIt, class OutIt> 
OutIt copy_n(InIt src, OutIt dest, size_t n) 
{
  if (!n) return dest;
  *dest = *src;
  while (--n)
    *++dest = *++src;
  return ++dest; 
} 

Обратите внимание, что std::copy_n() предполагает, что входной итератор может доставлять n объектов. При чтении из файла это может быть проблематично.


Отсутствует std::copy_n(), вы можете использовать std::generate_n.

template< typename InIt >
struct input_generator {
  typedef std::iterator_traits<InIt>::value_type value_type;

  input_generator(InIt begin, InIt end) begin_(begin), end_(end) {}

  value_type operator()()
  {
    assert(it_ != end);
    return *it_++;
  }

  Init begin_;
  Init end_;
};


std::vector<char> buffer;
buffer.reserve(42);

std::generate_n( std::back_inserter(buffer)
               , 42
               , input_generator(std::istream_iterator<char>(file))
               , input_generator(std::istream_iterator<char>()) );

Однако я не вижу в этом преимущества перед чтением непосредственно из файла, как avakar показал .

1 голос
/ 30 сентября 2010

«Путь STL» - это использование copy_n, которое входит в STL, но не соответствует стандарту C ++.

0 голосов
/ 30 сентября 2010

Кредит из-за @sbi, я забыл о generate_n.

streambuf внутри file имеет функцию snextc, которая возвращает следующий символ, квалифицируя его как функцию генератора, один разего неявный аргумент this связан.

generate_n( back_inserter( buffer ), 42,
            tr1::bind( tr1::mem_fn( &streambuf::snextc ), file.rdbuf() ) );

Для vector, просто прочитайте напрямую.Это хорошо для deque или чего-либо другого.

0 голосов
/ 30 сентября 2010
char *buffer = new char[n];
file.read(buffer,n);
std::vector<char> myVector
for (int i=0;i<n;i++) myVector.push_back(buffer[i]);
delete [] buffer;

// myVector now holds the first n bytes of file.

Возможно, это не самый красивый и быстрый способ, но я бы так и сделал.

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