Проблема с fread () в c при чтении чисел с плавающей запятой из файла - PullRequest
0 голосов
/ 12 июля 2020

Используемые библиотеки

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

Создание набора данных со случайными числами с плавающей запятой и печать во вновь созданном файле

void createdataset(int Datasetsize,char * filename)
{
  FILE *f;
  int su;
  float v[Datasetsize];    

  srand((unsigned int)time(NULL));

  for(int i = 1; i<=Datasetsize;i++) 
    *(v+i)=((float)rand()/(float)(RAND_MAX)) * 100;

  f=fopen(filename,"wb");
  su=fwrite(v ,sizeof(float) , Datasetsize , f);
  printf("%d\n",su);
  fclose(f);
}

Чтение вновь созданного файла с помощью fread () и отображение количества успешных попыток. Он всегда дает неудачные попытки, как будто он читает 120 записей из 1000, а остальные повреждены. Мне нужно решить эту проблему.

void loadDataset (int DataSetSize, char *filename, float *v) 
{
  FILE *fp;
  int s;

  fp = fopen( filename , "r" );
  if( fp==NULL) 
    printf("File cant be opened");

  s=fread(v , sizeof(float), DataSetSize, fp );
  printf("%d\n",s);
  for( int i=0; i<DataSetSize; i++)
  {
    printf("\t%f",*(v+i));
  }

  fclose(fp);
}

Основная функция

void main()  
{ 
    char ch;
    FILE *fp;
    int datasetsize;
    char filein[50];
    char *fi=filein, ds; 

    printf("Enter the size of the datasetsize: ");
    scanf("%d",&datasetsize);

    float v[datasetsize];

    printf("%d\n",datasetsize);
    printf("Enter input file name: ");
    scanf("%s",filein);
    printf("%s\n",filein);
    createdataset(datasetsize,fi);
    loadDataset(datasetsize, fi, v);
}

Ответы [ 2 ]

1 голос
/ 12 июля 2020

Включая conio.h вы меньше Windows

делаете

su=fwrite(v ,sizeof(float) , Datasetsize , f);
...
s=fread(v , sizeof(float), DataSetSize, fp );

вы пишете и читаете двоичный код, под windows для записи и чтения двоичного файла вам необходимо использовать «wb» и «rb», поэтому вам нужно заменить

f=fopen(filename,"w");
...
fp = fopen( filename , "r" );

на

f=fopen(filename,"wb");
...
fp = fopen( filename , "rb" );

но см. Также примечания ниже

из этого:

В createdataset :

вы не проверяете, удалось ли вам открыть файл, вам нужно проверить fp не NULL , например, используя perror, чтобы указать причину:

if (fp == NULL)
{
  perror("cannot open file to write"); 
  exit(-1);
}

Также сделать

*(v+i)=...

is не очень читабельно для установки элементов массива, просто сделайте

v[i] = ...

В loadDataset вы не можете сделать

if( fp==NULL) 
printf("File cant be opened");

и продолжить, как там не является ошибкой, вам нужно остановить выполнение функции, выполнив return или поместив остальные в ветку else, и снова вы можете использовать perror для обозначения проблемы:

if (fp == NULL)
{
   perror("cannot open the file to read");
   exit(-1);
}

Также сделать

printf("\t%f",*(v+i));

не очень читается для доступа к элементу массива, просто сделайте

printf("\t%f", v[i]);

In main :

scanf("%d",&datasetsize);

, если пользователь не вводит допустимый int, поведение не определено после того, как datasetsize не установлен, лучше сделать, например:

if ((scanf("%d",&datasetsize) != 1) || (datasetsize < 1)) {
  puts("invalid size);
  return -1;
}

Также

char filein[50];
...
scanf("%s",filein);

имеет неопределенное поведение, если пользователь вводит более 49 символов, сделайте

 scanf("%49s",filein);

даже лучше проверить scanf возвращает 1 в случае, если stdin перенаправляется в пустой входной файл

0 голосов
/ 12 июля 2020

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

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<time.h>
void createdataset(int Datasetsize, char *filename, float *v)
{
    FILE *f;
    int su;

    f = fopen(filename, "wb");
    if (!f)
    {
        printf("Error creating file. Program aborted...\n");
        abort();
    }

    printf("Writing %d entries to file \"%s\".\n", Datasetsize, filename);
    srand((unsigned int)time(NULL));
    for (int i = 1; i <= Datasetsize; i++)
    {
        *(v + i) = ((float)rand() / (float)(RAND_MAX)) * 100;
        printf("\t%f\n",*(v+i));
    }
    su = fwrite(v, sizeof(float), Datasetsize, f);
    printf("Wrote %d floats to file\n", su);
    fclose(f);
}

void loadDataset(int DataSetSize, char *filename, float *v)
{
    FILE *fp;
    int s;
    fp = fopen(filename, "rb");
    if (fp == NULL)
    {
        printf("File cant be opened");
        return;
    }

    s = fread(v, sizeof(float), DataSetSize, fp);
    printf("Read data set composed of %d entries.\n", s);
    for (int i = 0; i < DataSetSize; i++)
    {
        printf("\t%f\n", *(v + i));
    }

    fclose(fp);
}

int main(int argc, char *argv[])
{
    char ch;
    FILE *fp;
    int datasetsize;
    char filein[50];
    char *fi = filein, ds;

    printf("Enter the size of the datasetsize: ");
    scanf("%d", &datasetsize);
    printf("%d\n", datasetsize);

    float v_out[datasetsize];
    float v_in[datasetsize];

    printf("Enter input file name: ");
    scanf("%s", filein);
    printf("%s\n", filein);

    createdataset(datasetsize, fi, v_out);
    loadDataset(datasetsize, fi, v_in);

    int errors=0;
    for (int i=0; i<datasetsize; i++)
        if (v_in[i] != v_out[i])
        {
            printf("Error in/out in position %d, v_in=%f, v_out=%f\n", i, v_in[i], v_out[i]);
            errors++;
        }

    printf("Completed with %d error(s).\n", errors);
}

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

...