Home > database >  Access Violation error when using fscanf to read values from .txt file into a dynamically allocated
Access Violation error when using fscanf to read values from .txt file into a dynamically allocated

Time:12-13

I'm trying to write a function that stores the position vectors (pos_x, pos_y, pos_z) of N bodies into a dynamic array. However, an access violation error is given when using fscanf to read the values into the array. I'm unsure whether this is because the memory is being assigned incorrectly (it should be correct as it's taken from another function), or the values are being read incorrectly. The position vectors in the initial_positions.txt file are in this format (without the headers):

pos_x, pos_y, pos_z

1 2 3
4 5 6
7 8 9
1 2 3
4 5 6

My function:

int main()
{
int numberOfBodies = 5;
ReadInitialPositions(numberOfBodies);
return 0;
}

double **ReadInitialPositions(int numberOfBodies)
{
int row = 0;
int column = 0;
double **initialPositions = malloc(sizeof(double*) * numberOfBodies);

for (row = 0; row < numberOfBodies; row  )
    {
    initialPositions[row] = malloc(sizeof(double) * 3);
    }

for (row = 0; row < numberOfBodies; row  )
    {
    for (column = 0; column < numberOfBodies; column  )
        {
        printf(" %lf", initialPositions[row][column]);
        }
    printf("\n");
    }

FILE *file = fopen("initial_positions.txt", "r");

if (file == NULL)
    {
    printf("\nUnable to access the 'initial_positions.txt' file.\n");
    exit(1);
    }
else
    {
    while (fscanf(file, "%lf %lf %lf", &initialPositions[row][column], &initialPositions[row][column   1], &initialPositions[row][column   2]) != EOF)
        {
        printf("%lf", initialPositions[row][column]);
        row  ;
        }
    }

fclose(file);
free(initialPositions);
return initialPositions;
}

Would really appreciate any help:)

CodePudding user response:

  1. You allocate and display the uninitialized data in the in the first loop, but don't reset row and column before you try to read data into the array so you write out of bounds.

  2. Your column boundary is incorrect (should be 3 not numberOfBodies).

  3. When reading the data you use both column and a manual index. As you are not iterating over columns just hard-code the column indices.

  4. Check that fscanf() actually read the 3 fields you expected, otherwise those variables are uninitialized.

  5. Don't free the data that you just read as you are returning it caller.

  6. Use a constant instead of hard-coding the magic value 3.

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

#define COLS 3

double **ReadInitialPositions(int numberOfBodies) {
    double **initialPositions = malloc(numberOfBodies * sizeof(double *));
    for (int row = 0; row < numberOfBodies; row  ) {
        initialPositions[row] = malloc(COLS * sizeof(double));
    }

    FILE *file = fopen("initial_positions.txt", "r");
    if (!file) {
        printf("\nUnable to access the 'initial_positions.txt' file.\n");
        exit(1);
    }
    for(int row = 0; row < numberOfBodies; row  ) {
        int rv = fscanf(file, "%lf %lf %lf", &initialPositions[row][0], &initialPositions[row][1], &initialPositions[row][2]);
        if(rv == EOF) break;
        if(rv != 3) {
            printf("error\n");
            break;
        }
        for (int column = 0; column < COLS; column  ) {
            printf(" %lf", initialPositions[row][column]);
        }
        printf("\n");
    }
    fclose(file);
    return initialPositions;
}

int main() {
    double **d = ReadInitialPositions(5);
}

and the output is:

 1.000000 2.000000 3.000000
 4.000000 5.000000 6.000000
 7.000000 8.000000 9.000000
 1.000000 2.000000 3.000000
 4.000000 5.000000 6.000000

Here is a more generic version that figures out how many rows there are in the file:

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

#define COLS 3

int ReadInitialPositions(const char *pathname, double (**a)[COLS], size_t *rows) {
    FILE *file = fopen(pathname, "r");
    if (!file) {
        printf("\nUnable to access the '%s' file.\n", pathname);
        return 1;
    }
    *a = NULL;
    for(*rows = 0;; (*rows)  ) {
        double x, y, z;
        int rv = fscanf(file, "%lf %lf %lf", &x, &y, &z);
        if(rv == EOF) {
            break;
        }
        if(rv != 3) {
            printf("error\n");
            break;
        }
        double (*tmp)[COLS] = realloc(*a, sizeof(double[(*rows) 1][COLS]));
        if(!*tmp) {
            printf("realloc failed\n");
            fclose(file);
            return 1;
        }
        *a = tmp;
        (*a)[*rows][0] = x;
        (*a)[*rows][1] = y;
        (*a)[*rows][2] = z;
    }
    return 0;
}

int main() {
    double (*a)[COLS];
    size_t rows;
    if(ReadInitialPositions("initial_positions.txt", &a, &rows)) {
        printf("ReadInitialPositions() failed\n");
        return 1;
    }
    for(size_t row = 0; row < rows; row  ) {
        for (size_t column = 0; column < 3; column  ) {
            printf(" %lf", a[row][column]);
        }
        printf("\n");
    }
}
  • Related