БлогNot. Может ли ifstream извлечь вещественные числа из произвольного текстового файла.....

Может ли ifstream извлечь вещественные числа из произвольного текстового файла...

Про "подводные камни" при извлечении из текстового файла числовых значений нужного типа говорилось в этой заметке (про fscanf на "грязных" файлах), а также здесь и в "частых ошибках" (про локаль). Тем не менее, во всех этих случаях мы использовали классический способ чтения с помощью функции fscanf из библиотеки <cstdio>.

Но подобная же проблема возникает и при работе с потоками ввода ifstream. Пока файл "правильный", например, содержит только вещественные числа и разделители, всё работает отлично, например:

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

void error(char *s, int exitcode) {
 puts("\n");
 puts(s);
 puts("\nPress Enter to exit...");
 fflush(stdin); getchar();  exit(exitcode);
}

int main() {
 ifstream F;
 F.open("data.txt", ios::in);
 if (!F) error("Can't open file data.txt",1);
 double a;
 //основная часть
 while (!F.eof()) {
  F >> a;
  cout << a << " "; //Обработка очередного значения a - здесь
 }
 //
 F.close();
 error("OK", 0);
}

...и вот такой простейший файл data.txt для этой программы:

1.5  2


3.5

Стоит нам "замусорить" data.txt не-числами, как программа "зацикливается" на последнем прочитанном значении нужного типа.

Суть решения - такая же, как по первой ссылке, по крайней мере, более простого кода я придумать не смог (показана только ограниченная строчными комментариями "основная часть"):

//основная часть
while (!F.eof()) {
 if (F >> a) {
  cout << a << " "; //Обработка очередного значения a - здесь
 }
 else {
  F.clear();
  F.ignore(1);
 }
}
//

Мы просто пропускаем следующий символ, пока не найдём допустимого числа :) По крайней мере, вот с таким data.txt программа справилась:

1.5 A=-2.5 

I am not a number=3.3, i too!1e10

Выведено следующее:

1.5 -2.5 3.3 1e+10

OK

Press Enter to exit...

Решения мощнее, но и сложнее - вектора, алгоритмы и т.п.

Кстати, впечатление, что методы fstream не реагируют на локаль, по крайней мере, установка setlocale(LC_ALL, "RUS"); не заставляет программу считать разделителем целой и дробной части запятую вместо точки. Как узнать, в какую именно "текущую папку" помещать файл data.txt - тут.

01.12.2016, 00:04 [4923 просмотра]


теги: c++ ошибка форматы studio

К этой статье пока нет комментариев, Ваш будет первым