БлогNot. С++: читаем текстовый файл в вектор строк

С++: читаем текстовый файл в вектор строк

Немного познакомившись с векторами и поточными классами, это легко сделать.

Предположив, что юникод-файл с именем data.txt расположен в текущей папке консольного проекта, прочитаем его строки в вектор из элементов string, а затем выведем в консоль общее количество строк и символов в файле.

Обратите внимание, что если в конце файла есть "лишний" перевод строки, на которую можно поставить курсор, но она не содержит ни одного символа, отдельной строкой такая позиция считаться не будет:

Здесь
Три
Строки
|

Также стоит посмотреть, как находится сумма длин строк стандартным методом accumulate из библиотеки <numeric>, содержащий "заготовки" для реализации типовых алгоритмов. При этом для Юникода посчитается именно "общее количество байт, отведённое под все символы", исключая "двойной" для Windows символ CR/LF (\r\n, возврат каретки и перевод строки). Для приведённого выше теста получим:

3 string(s)
28 chars(s) without endl

при размере юникод-файла 34 байта.

"|" в последней строке тестового файла - не символ, а обозначение положения курсора при наличии CR/LF после слова "Строки".

Если последняя строка не завершается CR/LF и файл имеет размер 32 байта, ответы всё равно не изменятся :)

#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <numeric> /*библиотека для стандартных алгоритмов сумма, произведение и т.п.*/
using namespace std;

void error (string message,int errorcode) {
 cout << endl << message;
 system("pause>nul"); 
 exit(errorcode);
}

int main() {
 string line;
 vector <string> v;
 ifstream file("data.txt"); /*файл - в Юникоде (utf-8)*/
 if (!file) {
  error(string("Error opening output file"),1);
 }
 while (getline(file, line)) {
  v.push_back(line);
 }

 cout << endl << v.size() << " string(s)";

 int chars = accumulate(v.begin(), v.end(), 0, [](int sum, const string &item) {
    return sum + item.size();
 });
 cout << endl << chars << " chars(s) without endl";
 
 system("pause>nul"); return 0;
}

В принципе, при построчном чтении файла в вектор строк, основной цикл обработки можно было организовать и так:

do {
  file >> line;
  v.push_back(line);
 } while (!file.eof());

При посимвольном чтении из файла решение будет примерно таким:

/* Пример С++ для посимвольного считывания текста из многострочного тестового файла
с запоминанием каждого абзаца внутри вектора */
#include <fstream>  //Для файловых потоков
#include <iostream> 
#include <string>   //Для контейнера string
#include <vector>  //Для контейнера vector
#include <iterator> //Для вывода элементов вектора  на экран с помощью алгоритма copy
#include <string>
#include <windows.h>

using namespace std;

int main() {
 setlocale(LC_ALL, "RUS"); SetConsoleCP(1251); SetConsoleOutputCP(1251);

 int ch = 0;  //Это переменная, в которую нужно считывать символы
 string s;  //Это строка, она в примере будет абзацем
 vector<string> v; //Вектор строк 

 const char *filename = "data.txt";

 //Считаем текст с форматированием
 ifstream file(filename);     //открыли для чтения  файл
 while ((ch = file.get()) != EOF) {
  if (char(ch) != '\n') s = s + char(ch);
  //Считываем символ из файла и сразу проверяем его на признак переноса строки. 
  else {
   v.push_back(s); //Если текущий символ перенос, то записываем строку в вектор
   s.clear(); //Очищаем строку
  }
 }
 v.push_back(s); //Дописываем последнюю строку в вектор
 file.close();

 copy(v.begin(), v.end(), std::ostream_iterator<string>(cout, "\n"));
 //Вывожу вектор на экран
 cin.get();
 return 0;
}

теги: алгоритм c++ textprocessing форматы

03.05.2017, 11:19; рейтинг: 2715