Как разобрать файл, содержащий шестнадцатеричные числа в форме -0x1.0c7474fp + 8 в c ++? - PullRequest
0 голосов
/ 17 сентября 2018

Я пытаюсь разобрать файл data.txt, содержащий шестнадцатеричные формы -0x1.0c7474fp+8:

-0x1.e51b67p+0 0x1.0b18ef5p+8 0x1.9c6075p+8 -0x1.190d44p+4
-0x1.e4f7838p+0 0x1.0b6446dp+8 0x1.9d779b8p+8 -0x1.16436ap+3
-0x1.e4555bp+0 0x1.0b6d446p+8 0x1.9e28c4ap+8 -0x1.1f8b0ep+3
-0x1.e3b9598p+0 0x1.0b7982cp+8 0x1.9edf5f8p+8 -0x1.f80bc6p+2
-0x1.e2f5896p+0 0x1.0b70bd7p+8 0x1.9f75c6ap+8 -0x1.07390ep+3
-0x1.e21d2dep+0 0x1.0b5961cp+8 0x1.9fef6e6p+8 -0x1.031012p+3
-0x1.e225b96p+0 0x1.0bbc104p+8 0x1.a12c75cp+8 -0x1.06951cp+3
-0x1.e17ec4cp+0 0x1.0bc35b7p+8 0x1.a1de5a6p+8 -0x1.25f138p+3
-0x1.e0e7f36p+0 0x1.0c140edp+8 0x1.a300c22p+8 -0x1.417644p+3
-0x1.e0e7e0ap+0 0x1.0c7474fp+8 0x1.a43f084p+8 -0x1.359f22p+3
-0x1.e076e6cp+0 0x1.0c93aebp+8 0x1.a50efaap+8 -0x1.00e406p+4
-0x1.e1c339cp+0 0x1.0ec7d62p+8 0x1.ab2777p+8 -0x1.1b6134p+3
-0x1.e0614eap+0 0x1.0e669d1p+8 0x1.ab301b8p+8 -0x1.6a997cp+2
-0x1.e01577p+0 0x1.0e9f2e5p+8 0x1.ac33c36p+8 -0x1.62eb42p+2
-0x1.de237dcp+0 0x1.0df5506p+8 0x1.abd2c42p+8 -0x1.8951c2p+2

Я пишу c++ код безуспешно:

#include <iostream>
#include <fstream>

int main()
{
    float a, b, c, d;

    std::ifstream ifs("data.txt");

    int n = 0;
    while(ifs >> std::hex >> a
              >> std::hex >> b
              >> std::hex >> c
              >> std::hex >> d)
    {
        std::cout << a << " "
                  << b << " "
                  << c << " "
                  << d << std::endl;
        ++n;
    }
    std::cout << "n=" << n << std::endl;

    return 0;
}

Редактировать : Я пытался использовать std::hexfloat, но он все еще не работает с gcc, как показано в этом примере .

Ответы [ 2 ]

0 голосов
/ 02 октября 2018

кажется, что GCC все еще не может правильно обработать "hexFloat", проверьте gcc tracker:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59987

Как насчет этого простого альтернативного решения?

#include <iostream>

int main() {
    const char *data = "-0x1.e51b67p+0 0x1.0b18ef5p+8 0x1.9c6075p+8 -0x1.190d44p+4 -0x1.e4f7838p+0 0x1.0b6446dp+8 0x1.9d779b8p+8 -0x1.16436ap+3";

    char *end;
    for (float f = strtof(data, &end); data != end; f = strtof(data, &end))
    {
        data = end;
        if (errno == ERANGE){
            printf("range error, got ");
            errno = 0;
        }
        printf("%a\n", f);
    }

    return 0;
}

https://wandbox.org/permlink/69MpeNKexPWaOiZc

0 голосов
/ 17 сентября 2018

-0x1.e51b67p+0 gobble-de-gook - это вывод std::hexfloat, дополнения к стандартной библиотеке C ++ в стандартной редакции C ++ 11.

Если вы замените

while(ifs >> std::hex >> a
          >> std::hex >> b
          >> std::hex >> c
          >> std::hex >> d)

с

while(ifs >> std::hexfloat >> a
          >> std::hexfloat >> b
          >> std::hexfloat >> c
          >> std::hexfloat >> d)

, и ваш компилятор поддерживает C ++ 11 и hexfloat (в этом G ++ немного запаздывает), вам следует идти вперед.

Edit: G ++ был медленным, включая std::hexfloat в заголовках.К сожалению, на сегодняшний день, GCC 8.2, поддержка std::hexfloat является неполной и не работает.Этот ответ не работает для Аскера.

Правка 2: Я заслуживаю того, чтобы упасть на свой меч для этого, но, к счастью, у меня нет меча.В моем навязчивом изучении того, почему это не работает в C ++, и в попытке найти вежливый способ заставить это работать в C ++, я полностью забыл тот факт, что это прекрасно работает в C.

С std::hexfloatзадерживается, пока разобраны формулировки стандарта C ++, давайте следовать Git-R Готово!В принципе, используйте C и оберните его в функцию, чтобы потом ее можно было легко заменить на идиоматический C ++.

#include <cstdio>
#include <iostream>

int main()
{
    float a, b, c, d;

    FILE *f = fopen("data.txt", "r");

    if (f == NULL)
    {
        std::cerr << "Unable to open file."
        return -1;
    }
    int n = 0;
    while(fscanf(f, "%a %a %a %a", &a, &b, &c, &d) == 4)
    {
        std::cout << a << " "
                  << b << " "
                  << c << " "
                  << d << std::endl;
        ++n;
    }
    std::cout << "n=" << n << std::endl;

    return 0;
}
...