Чтение только значений с плавающей точкой из текстового файла

У меня есть файл данных в текстовом формате. У него 2 колонны, во-первых, бесполезно, чтобы я мог игнорировать это, а во-вторых, это то, что мне нужно. В столбце есть разные значения в каждой строке, такие как строка, число с плавающей запятой и т. Д. Для некоторых вычислений мне нужно использовать только члены этого столбца. Я пошел по этому пути, сначала объявил массив с плавающей точкой и прочитал значения и сохранил массив с «>>» основная команда.

Проблема в том, что когда пришла строка с плавающей точкой, функция чтения работает как неработающая. Он читает не плавающие значения как «0» и сохраняет их как таковые. Это нормально, но после этого считывает целые значения как «0», даже если это было число с плавающей точкой.

Datafile.txt (пример)

aa 1.1
bb 2.2
cc 3.0
dd somestring
ee 4.3
ff 4.9

Код (пример)

 do
{
dfile >> a >> dat[i];
ofile << dat[i]<<endl;
cout << dat[i]<<endl;
i++;

}while(dfile.eof());

Выходной файл (пример)

1.1
2.2
3.0
0
0
0
..goes

Я думал о двух способах решения проблемы. Первый — пропустить строки без плавающего. Второй — чтение строки за период. Потому что значения с плавающей запятой перечислены в последовательности.

0

Решение

Сначала прочитайте строку, а затем попытайтесь преобразовать в число:

std::string maybeNumber;
while (dfile >> a >> maybeNumber)
{

std::istringstream is(maybeNumber);
float number = 0.0f;
if (is >> number)
{
dat[i] = number;
i++;
}
}

(Вы не хотите использовать eof, Каждый думает, что хочет использовать eof, но это почти всегда не то, что им нужно. Увидеть этот вопрос для деталей.)

2

Другие решения

Это нормально, но после этого считывает целые значения как «0», даже если это было число с плавающей точкой.

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

Что касается решения проблемы, прочитайте каждую строку как std::stringзатем разделите строку на std::vector<std::string>, Если вектор не содержит двух элементов или если второй не является double, ничего не делать, иначе обработать строку.

Что-то вроде этого:

std::string line;
while (std::getline(dfile, line))
{
auto const elements = parse(line);
if (size(elements) == 2 && is_double(elements[1]))
{
// process
}
}

Теперь, когда вы решили проблему на более высоком уровне абстракции, все, что вам нужно сделать, это реализовать что-то вроде parse а также реализовать что-то вроде is_double (делить & завоевать).

Также обратите внимание, что тип C ++ по умолчанию с плавающей точкой double и не float, Если есть сомнения, используйте double,

1

Я бы использовал такой алгоритм:

Для каждой строки в файле:

  1. Разбить строку по пробелам
  2. Для каждого результата этого разделения:
    1. Macht с регулярным выражением «^ \ d + (\. \ D +)? $»
    2. Если строка соответствует регулярному выражению, преобразовать в float и сохранить в массиве результатов
1

с помощью GetLine а также regex_token_iterator

#include <regex>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>

int main()
{
std::vector<float> v;
std::regex reg("-?\\d+(\\.\\d+)?");
const char* filename="myfile.txt";

std::ifstream ifs(filename,std::ios::binary);

for(std::string s;std::getline(ifs,s);)
for(std::sregex_token_iterator rgi(s.begin(),s.end(),reg);rgi!=std::sregex_token_iterator();++rgi)
v.push_back(std::stof(rgi->str());

std::copy(v.begin(),v.end(),std::ostream_iterator<float>(std::cout," ");
return 0;
}
1
По вопросам рекламы [email protected]