Блокировать проблемы ввода-вывода с чтением с плавающей точкой - C - PullRequest
0 голосов
/ 09 мая 2018

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

This program stores a business inventory.
Please enter item data (part number, quantity, price): *2, 3, 1.6*
Please enter item data (part number, quantity, price): *3, 1, 5.3*
Please enter item data (part number, quantity, price): *0*
Thank you. Inventory stored in file inventory.txt

Введите код программы

   #include <stdio.h>
#include <stdlib.h>

int main(int argc, int argv[])
{
int pnum=1, quantity;
float price;
FILE *fp1;

fp1 = fopen("inventory.txt", "wb+");
if(fp1 == NULL)
{
    printf("Can't open!\n");
    exit(EXIT_FAILURE);
}

printf("This program stores a business inventory.\n");
while(pnum != 0)
{
printf("Please enter item data (part number, quantity, price): ");
scanf("%d, %d, %f", &pnum, &quantity, &price);
printf("%d, %d, %f", pnum, quantity, price);
fwrite(&pnum, sizeof(int), 1, fp1);// Is there a way to combine these 3 fwrites into 1?
fwrite(&quantity, sizeof(int), 1, fp1);
fwrite(&price, sizeof(float), 1, fp1);
}
printf("Thank you. Inventory stored in file inventory.txt");
fclose(fp1);
return 0;


}

Компилятор с программой чтения (* * - пользовательский ввод)

Below are the items in your inventory.
Part#    Quantity        Item Price
2         3                1070386381?
3         1                1084856730?
0?        1                1084856730?

Считать код программы

#include <stdio.h>
#include <stdlib.h>

int main()
{
int pnum, quantity;
float price;
FILE *fp1 = fopen("inventory.txt", "rb");
if(fp1 == NULL)
{
    printf("Can't open!");
    exit(EXIT_FAILURE);
}
printf("Below are the items in your inventory.\n");

printf("Part#\tQuantity\t Item Price\n");
while (fread(&pnum, sizeof(int), 1, fp1) == 1)//Is there a way to combine these 3 freads into 1 line of code?
{
    printf("%5d\t", pnum);
}
while (fread(&quantity, sizeof(int), 1, fp1) == 1)
{
    printf("%8d\t", quantity);
}
while (fread(&price, sizeof(float), 1, fp1) == 1)
{
    printf("$");
    printf("%9.2f\n", price);

}
fclose(fp1);
return 0;

}

Как вы, возможно, заметили, scanf - это scanf, и он должен быть связан с моим float, но я не смог выяснить, как это исправить, потому что без scanf ничего не сохраняется в моем файле inventory.txt ( Я не включил файл .txt, потому что он двоичный), и по какой-то причине, когда я набираю 0, чтобы разорвать цикл, он сохраняет 0 в файле. Если нужна какая-то другая информация, я могу ее предоставить, но я думаю, что предоставил все. Спасибо за любую помощь, и счастливого кодирования:)

Ответы [ 2 ]

0 голосов
/ 09 мая 2018

Странные значения, которые вы получаете в своей «программе чтения», полностью действительны, но ... Они закодированы как значение с плавающей запятой IEEE-754. Если вы закодируете 5.3 как IEEE-754, вы получите 0x40a9999a, что равно 1084856730, поэтому ваши показания хороши, а что-то нехорошее с его выводом.

Измените ваш формат printf с %9.2f на %f. Если это не поможет, попробуйте форсировать приведение цены: fread((void*)(&price), sizeof(float), 1, fp1).

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

0 голосов
/ 09 мая 2018
  • Ноль вставляется в массив, потому что ваш цикл while прерывает только после вызовов fwrite. Вы можете использовать break Я полагаю, чтобы выйти сразу после scan.
  • Чтобы объединить записи и чтения, вы можете использовать структуру, но обратите внимание, что вам, вероятно, следует сериализовать и десериализовать из / в точно такую ​​же структуру из-за padding .
  • Я подозреваю , что ваши fread в float дают странные результаты из-за неправильного порядка записи / чтения или заполнения. Попробуйте прочитать и записать в структуру и посмотреть, решит ли это вашу проблему. Если это не сработает, попробуйте вывести шестнадцатеричное значение вашего числа с плавающей запятой %x. Затем сравните с ожидаемым результатом.

Рассмотрим следующий код:

#include <stdio.h>
#include <fcntl.h> // for open
#include <unistd.h> // for close


typedef struct
{
    float price;
    int pnum;
    int quantity;
} shoppingItem;


void writeToFile(FILE *fp) {    
    shoppingItem input1 = {1.1,2,3};
    shoppingItem input2 = {3.1412,42,666};
    fwrite(&input1, sizeof(shoppingItem), 1, fp);
    fwrite(&input2, sizeof(shoppingItem), 1, fp);
    printf("%f %d %d\n", input1.price, input1.pnum, input1.quantity);
    printf("%f %d %d\n", input2.price, input2.pnum, input2.quantity);
}

void readFromFile(FILE *fp) {
    shoppingItem output1 = {0.0,0,0};
    shoppingItem output2 = {0.0,0,0};
    fread(&output1, sizeof(shoppingItem), 1, fp);
    fread(&output2, sizeof(shoppingItem), 1, fp);
    printf("%f %d %d\n", output1.price, output1.pnum, output1.quantity);
    printf("%f %d %d\n", output2.price, output2.pnum, output2.quantity);
}

int main()
{
    FILE *fp = fopen("inventory.txt", "wb+");
    if(fp == NULL)
    {
        printf("Can't open!\n");
        return 1;
    }

    writeToFile(fp);
    rewind(fp);
    readFromFile(fp);

    if (fclose(fp) == 0) {
        printf("Done\n");
        return 0;
    } else {
        printf("Error on closing file\n");
        return 1;
    }
}
...