Вопрос по fstream, split, c++, stdvector – Лучший способ разделить вектор на два меньших массива?

22

Что я пытаюсь сделать:

Я пытаюсь разделить вектор на два отдельных массива. Текущий вектор int содержит элемент на строку в текстовом файле. Текстовый файл представляет собой список случайных целых чисел.

Как я планирую это сделать:

Моя текущая идея состоит в том, чтобы создать два регулярных массива int, затем выполнить итерацию по всему вектору и скопироватьп / 2 элементы к каждому из массивов.

Что я хотел бы знать:

Какой самый элегантный способ выполнить мою задачу? У меня есть ощущение, что я могу сделать это, не повторяя несколько раз вектор.

Код:

#include <vector>
#include <fstream>
#include <iterator>
#include <iostream>
using namespace std;

vector<int> ifstream_lines(ifstream& fs)
{
  vector<int> out;
  int temp;
  while(fs >> temp)
  {
    out.push_back(temp);
  }
  return out;
}

vector<int> MergeSort(vector<int>& lines)
{
  int split = lines.size() / 2;
  int arrayA[split];
  int arrayB[split];
}

int main(void) 
{
  ifstream fs("textfile.txt");
  vector<int> lines;
  lines = ifstream_lines(fs);

  return 0;
}

Спасибо :)

если вы не планируете изменять размер двух массивов, вы можете посмотреть наarray_view sp2danny
Я бы порекомендовал что-то из<algorithm> заголовок (en.cppreference.com/w/cpp/algorithm).std::copy или жеstd::move может представлять интерес. Zyx 2000
Мне нравится, как задают вопрос. Вы не часто видите такие структурированные вопросы от новых пользователей. MOnsDaR

Ваш Ответ

4   ответа
2

то вы можете сделать:

int *array_1 = &lines[0];
int *array_2 = &lines[lines.size() / 2];

На самом деле, array_1 и array_2 являются указателями на начало и середину вектора. Это работает, поскольку STL гарантирует, что векторы хранят свои элементы в непрерывной памяти. Обратите внимание, что ссылка на lines.begin () не может быть использована для этого.

2

Если вы не можете использовать код изXeo ответ из-за строгих правил компилятора или вы хотите более общий способ, попробуйтеstd::advance:

#include <vector>
#include <iterator>

size_t middle = input.size()/2;
std::vector<int>::const_iterator middleIter(input.cbegin());
std::advance(middleIter, middle);

std::vector<int> leftHalf(input.begin(), middleIter);
std::vector<int> rightHalf(middleIter, input.end());
1

используя итератор.

#include <iostream>
#include <vector>

int main()
{
   // Original vector of data
   std::vector<double> mainVec{1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0};
   // Result vectors
   std::vector<std::vector<double>> subVecs{};
   // Start iterator
   auto itr = mainVec.begin();
   // Variable to control size of non divided elements
   unsigned fullSize = mainVec.size();
   // To regulate count of parts
   unsigned partsCount = 4U;
   for(unsigned i = 0; i < partsCount; ++i)
   {
       // Variable controls the size of a part
       auto partSize = fullSize / (partsCount - i);
       fullSize -= partSize;
       // 
       subVecs.emplace_back(std::vector<double>{itr, itr+partSize});
       itr += partSize;
   }
   // Print out result
   for (const auto& elemOuter : subVecs)
   {
       std::cout << std::fixed;
       for (const auto& elemInner : elemOuter)
       {
           std::cout << elemInner << " ";
       }
       std::cout << "\n";
   }
}
55

Используйте итераторы.

std::vector<int> lines;
// fill
std::size_t const half_size = lines.size() / 2;
std::vector<int> split_lo(lines.begin(), lines.begin() + half_size);
std::vector<int> split_hi(lines.begin() + half_size, lines.end());

Поскольку диапазоны итераторов представляют полуоткрытые диапазоны[begin, end)вам не нужно добавлять 1 во второй начальный итератор:lines.begin() + half_size не копируется в первый вектор.

Обратите внимание, что такие вещи, как

int split = lines.size() / 2;
int arrayA[split];
int arrayB[split];

Не являются стандартными C ++ (и как таковые не переносимы). Это так называемые массивы переменной длины (VLA для краткости), и это вещь C99. Некоторые компиляторы имеют их как расширение при компиляции кода C ++ (GCC, Clang). Всегда компилировать с-pedantic получить предупреждение. Эти VLA действуют в стиле фанк для не POD-типов и, как правило, бесполезны, так как вы даже не можете их вернуть.

Очень хороший ответ, +1 за «вам не нужно добавлять 1 во второй начальный итератор» Jorge Leitão

Похожие вопросы