БлогNot. C++: прочитать из файла только числа в двумерный или одномерный контейнер

C++: прочитать из файла только числа в двумерный или одномерный контейнер

Допустим, имеется текстовый файл 1.txt в папке исходника с таким содержимым:

 1   2
3  4.5    4
куку 123 строка будет пропущена
1e4 222

Прочитаем из него числа double, положим в вектор векторов и выведем, что получилось.

При чтении будем игнорировать строку, в которой не удалось распознать хотя бы одну лексему как число double (нетрудно добавить вывод номеров таких строк для контроля ошибок).

Пример проверен в консоли Visual Studio 2019.

#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
#include <sstream>
#include <fstream>
using namespace std;

int main() {
  ifstream f("1.txt"); //из текущей папки
  if (!f) {
   cout << "No file!"; return 1;
  }
  //любое количество строк с любым количеством чисел читаем в вектор векторов
  vector <vector<double> > data;
  string line;
  do {
   getline (f, line, '\n');
   istringstream reader(line);
   vector <double> lineData;
   double val;
   string::const_iterator i = line.begin();
   bool error = false;
   do {
    double val;
    reader >> val;
    if (reader.fail()) {
     error = true;
     break; //пропуск строк с не-числами
    }
    lineData.push_back(val);
   } while (!reader.eof());
   if (!error) data.push_back(lineData);
  } while (!f.eof());

  //что вышло
  cout.precision (2);
  for (int i = 0; i < data.size(); i++) {
   for (int j = 0; j < data[i].size(); j++) {
    cout << fixed << setw(8) << data[i][j] << " ";
   }
   cout << endl;
  }
  return 0;
}

А получилось вот что:

    1.00     2.00
    3.00     4.50     4.00
10000.00   222.00

Теперь легко проверить, что данные отвечают нашим требованиям, например, все вложенные вектора содержит одинаковое количество чисел (если есть такое требование).

Допустим, показанный выше подход сложноват. Как ещё можно поступить?

Именно в таких случаях программисты и придумывают форматы данных, соблюдать которые должен уже тот, кто готовит данные для программы.

Что мешает нам потребовать, чтобы в начале файла располагались 2 числа, указывающие размерность матрицы, и писать потом уже вполне школьный код?

Файл 1.txt станет, например, таким:

2 2
 1   2.5
3      4

А пример таким:

#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
#include <sstream>
#include <fstream>
using namespace std;
 
int main() {
 ifstream f("1.txt"); //из текущей папки
 if (!f) {
  cout << "No file!"; return 1;
 }
 double **data;
 int n, m;
 f >> n >> m;
 if (f.fail() || n < 1 || m < 1) {
  cout << "Bad size or not found 2 numbers"; return 2;
 }
 data = new double * [n];
 if (!data) {
  cout << "No memory"; return 3;
 }
 for (int i = 0; i < n; i++) {
  data[i] = new double [m];
  if (!data[i]) {
   cout << "No memory"; return 4;
  }
 }
 //читаем и сразу выводим, что вышло
 cout.precision(2);
 bool error = false;
 for (int i = 0; i < n; i++) {
  for (int j = 0; j < m; j++) {
   f >> data[i][j];
   if (f.fail()) { error = true; data[i][j] = 0; f.clear(); }
   cout << fixed << setw(8) << data[i][j] << " ";
  }
  cout << endl;
 }
 if (error) cout << "There is error(s) in file, please check it!";
 return 0;
}

Заодно ловим самым примитивным образом ошибки в данных, но, хотя бы, не зависим от лишнего пробела между числами и т.п.

В коде ниже мы читаем просто вектор элементов double из файла data.txt с проверкой корректности чисел:

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

int main() {
 vector <double> data;
 double val;
 ifstream f ("data.txt");
 if (!f) {
  cout << "Can't open file"; return 1;
 }
 do {
  f >> val;
  if (f.fail()) {
   f.clear();
   while (1) {
    char c = f.get();
    if (c == ' ' || c == '\n' || f.eof()) break;
   }
  }
  else {
   data.push_back(val);
  }
 } while (!f.eof());
 f.close();
 
 cout << endl;
 for (int i = 0; i < data.size(); i++) cout << data[i] << " ";

 return 0;
}

с таким файлом data.txt:

1 1.5    2    1e900
coocoo bad 



123

теги: программирование учебное c++ форматы числа

15.05.2020, 22:44; рейтинг: 39