shurrok
shurrok

Reputation: 831

How to read floats from file in c?

I am struggling with reading floats from a file which I created during the program lifetime. I was trying to rewind the file, I was trying to open and close file before reading it, I was trying to put values directly in the table and by another variable. Idk what can I do more, what's wrong here?

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

int main(void) {
    srand(time(NULL));

    float *tab;
    float x = 0.0;
    int i, size;
    FILE *fp;

    fp = fopen("data.txt", "w+");
    if (fp == NULL) {
        printf("Error");
        system("PAUSE");
        exit(1);
    }
    printf("Size of table: ");
    scanf("%d", &size);

    tab = (int*)malloc(size * sizeof(int));

    for (i = 0; i < size; i++) {
        tab[i] = (8.0 - 2.0) * (float)rand() / RAND_MAX + 2.0;
        fprintf(fp, "%.2f ", tab[i]);
    }
    for (i = 0; i < size; i++) {
        printf("%.2f ", tab[i]);
    }
    printf("\n");

    fp = fclose;
    fp = fopen("data.txt", "w+");
    tab = realloc(tab, 2*size);

    for (i = 0; i < size * 2; i+=2) {
        fscanf(fp, "%f", &x);
        printf("%.2f ", x);
        //tab[i + 1] = tab[i] / 2;
    }

    /*for (i = 0; i < size * 2; i++) {
        printf("%.2f \n", tab[i]);
    }*/


    fp = fclose;
    printf("\n");
    system("PAUSE");
    return 0;
}

Upvotes: 0

Views: 4328

Answers (1)

ad absurdum
ad absurdum

Reputation: 21323

There are a number of problems in this code. First, as noted in the comments, the initial allocation is wrong. You are allocating space for floats, not ints. You could have avoided this problem entirely if you had written the call to malloc() like this:

tab = malloc(sizeof(*tab) * size);

Here, the result of malloc() is not cast, since it is not necessary in C. Also, note that instead of using an explicit type for the argument to the sizeof operator, the identifier is used instead. This guarantees that whatever the type of tab, which must be a pointer, the result of sizeof will be correct. Also, you should always check to see if an allocation was successful.

fp = fclose is just wrong. This should be fclose(fp). After this, when you open the file again with "w+", the file is truncated to zero length, and you lose the data that was previously written. Since the file has already been opened with "w+", just use rewind(fp) here.

For the reallocation that you do, aside from that the arguments are not quite right here, there is a potential problem that you should be aware of. realloc() can return a null pointer in the event of an allocation error. If this happens, and you are directly assigning the result of realloc() to the pointer for which you are reallocating (tab), then you will lose the reference to previously allocated memory. This is a memory leak, and lost data. The way to do this is to store the result of realloc() in a temporary pointer, which you test. If the temporary pointer is a null pointer, there was an error; otherwise you can safely assign the return value to the original pointer.

And as already noted, when you call fclose() the final time, it needs to be fclose(fp).

Here is a modified code:

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

int main(void) {
    srand(time(NULL));

    float *tab, *temp;         // added temp for realloc() check
    float x = 0.0;
    int i, size;
    FILE *fp;

    fp = fopen("data.txt", "w+");
    if (fp == NULL) {
        printf("Error");
        system("PAUSE");
        exit(1);
    }
    printf("Size of table: ");
    scanf("%d", &size);

    /* You should always check for allocation errors */
    if ((tab = malloc(sizeof(*tab) * size)) == NULL) {
        fprintf(stderr, "Error in initial allocation\n");
        exit(EXIT_FAILURE);
    }

    for (i = 0; i < size; i++) {
        tab[i] = (8.0 - 2.0) * (float)rand() / RAND_MAX + 2.0;
        fprintf(fp, "%.2f ", tab[i]);
    }
    for (i = 0; i < size; i++) {
        printf("%.2f ", tab[i]);
    }
    printf("\n");

//    fclose(fp);                     // not fp = fclose;
//    fp = fopen("data.txt", "w+");   // when you reopen, the file is truncated
    rewind(fp);                       // but just do this

    /* Fixed this reallocation */
    temp = realloc(tab, sizeof(*tab) * size * 2);    
    if (temp == NULL) {
        fprintf(stderr, "Error in reallocation\n");
        exit(EXIT_FAILURE);
    }
    tab = temp;

    for (i = 0; i < size * 2; i+=2) {
        fscanf(fp, "%f", &x);
        printf("%.2f ", x);
        //tab[i + 1] = tab[i] / 2;
    }

    /*for (i = 0; i < size * 2; i++) {
        printf("%.2f \n", tab[i]);
    }*/


    fclose(fp);            // not fp = fclose;
    printf("\n");
    system("PAUSE");
    return 0;
}

Sample interaction:

Size of table: 10
2.65 5.67 5.21 3.22 3.07 4.29 5.96 5.96 5.15 7.36 
2.65 5.67 5.21 3.22 3.07 4.29 5.96 5.96 5.15 7.36 

Upvotes: 1

Related Questions