Разбирать текстовый файл, пока не найден float?

0

Я пытаюсь разобрать строки из текстового файла. Каждая строка представляет собой биржевой тикер и имеет тот же формат, имеющий случайное число строк (для названия компании + символ), за которым следует равномерное количество поплавков (одинаковое количество для каждой строки).

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

Примеры строк текста:

A.M. CASTLE & COMPANY CAS 15.71 0.55  3.63 31.57 17.97 8.99 7.79
AAR CORP AIR 17.79 0.19  1.08 30.62 18.45 10.51 38.26 
ABBOTT LABORATORIES ABT 45.14 0.01  0.02 -3.24 50.00 40.25 20.33 

Образец кода:

void parse(string filename){
    ifstream myfile;        
    string line;
    string current_word;

    myfile.open(filename);
    if (myfile.is_open()){
        while (getline(myfile, line))
        {
            stringstream current_line(line);
            while (current_line >> current_word){
                // How can I test when I have reached a float here?
            }
        }
    }
}
  • 2
    Вы должны включить в свой вопрос Минимальный, Полный и Проверяемый пример текущей попытки, чтобы мы лучше поняли, что именно вы делаете. Это поможет нам дать подходящий ответ.
  • 0
    Гарантируется ли, что перед первым числом с плавающей запятой не появятся никакие цифры?
Показать ещё 2 комментария
Теги:
parsing

4 ответа

2
Лучший ответ

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

int main()
{
    std::string line = "A.M. CASTLE & COMPANY CAS 15.71 0.55 3.63 31.57 17.97 8.99 7.79";

    std::istringstream iss(line); // convert the line into a stream

    std::string item;
    while(iss >> item) // read the stream items (space separated) one by one
    {
        float f;
        if(std::istringstream(item) >> f) // does this item read as a float?
        {
            // use f here if it does
            std::cout << f << " ";
        }
    }
}
1

Если вам гарантировано, что ни одна из строк перед поплавком не будет содержать цифру, вы можете просто сравнить каждый символ, пока не будет найдена цифра, и вы нашли первый символ поплавка.

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

0

Используйте регулярные выражения, доступные на С++ 11.

Дважды проверьте шаблон чисел с плавающей запятой. Например, мое выражение не позволяет вести знак.

#include <iostream>
#include <ostream>
#include <regex>
#include <sstream>
#include <string>

int main()
{
    std::istringstream input("A.M. CASTLE & COMPANY CAS 15.71 0.55 3.63 31.57 17.97 8.99 7.79");

    // Pattern for recognizing floating-point numbers
    std::regex pattern(R"(\d+\.(\d*)?((e|E)(\+|\-)?\d+)?)");

    for (std::string line; std::getline(input, line); )
    {
        // We have a successful read of one line
        // Now extract the floating-point numbers on that line

        auto first = std::sregex_iterator(line.cbegin(), line.cend(), pattern);
        auto last = std::sregex_iterator();
        for (; first != last; ++first)
        {
            double d = std::stof(first->str());
            std::cout << d << std::endl;
        }
    }

    return 0;
}
0

Вы можете использовать sscanf(), который выполнит запрошенную операцию в одной строке.

bool parseNameAndFloats(char const *input, char *name, unsigned int namesize, float *floatArray, unsigned int floatsize)
{
    // Assuming the sample string is representative, there 7 floats in it.
    if (floatsize < 7)
    {
        return false;
    }
    char *temp = strdup(input);
    if (temp == NULL)
    {
        // deal with allocation failure in strdup;
        return false;
    }
    int count = sscanf(input, "%[^0-9.]s %f %f %f %f %f %f %f", temp, floatArray, floatArray + 1, floatArray + 2, floatArray + 3, floatArray + 4,floatArray + 5, floatArray + 6);
    if (namesize > 0)
    {
        strncpy(name, temp, namesize);
        name[namesize - 1] = 0;
    }
    free(temp);
    return count == 8;
}

Есть те, которые будут критиковать sscanf(), а при неправильном использовании это может вызвать некоторые серьезные проблемы. Одной из таких причин я использую strdup() чтобы сделать копию исходной строки ввода. Это гарантировало получение мною буфера, достаточно большого, чтобы удерживать результаты преобразования %[^0-9.]s S. Затем я использую strncpy() для извлечения не более, чем поместится в предоставленный буфер, и обязательно завершите NUL.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню