Home > database >  fscanf segmentation fault, trying to read a file and put values in an array - c
fscanf segmentation fault, trying to read a file and put values in an array - c

Time:02-01

my friend is studying for an exam. He keeps receiving the segmentation fault on " while (fscanf(f, "%s %d %d", A[i].costruttore, A[i].ns, A[i].costo) != EOF)". How can I help him?

You can find his code below

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DIM 100
typedef struct
{
    char costruttore[20];
    int ns;
    int costo;
} memoria;

void lettura(memoria A[], int *n)
{
    int i = 0;
    FILE *f;
    f = fopen("memory.txt", "r");
    if( f == NULL ) {
    fprintf(stderr, "Couldn't open %s: %s\n", "memory.txt", strerror(errno));
    exit(1);
}
    while (fscanf(f, "%s %d %d", A[i].costruttore, A[i].ns, A[i].costo) != EOF)
        i  ;
    (*n) = i;
    fclose(f);
    for (i = 0; i < (*n); i  )
        printf("%s %d %d\n", A[i].costruttore, A[i].ns, A[i].costo);
}

int main()
{
    memoria A[DIM];
    int n;
    lettura(A, &n);
    return 0;
}

memory.txt content

PerKele 56 41
AM-Silicon 49 41
JKR 33 50
Atlantic 57 62
JADA 50 50
JKR 40 51
Drast 28 35
SGUZ 73 55
JADA 29 46
FARSTIC 65 30
Drast 41 36
FRoW 48 67
FARSTIC 39 62
Drast 27 44
SGUZ 51 50
Drast 58 60
Liquid 41 71
SWP3 50 63
KRRAM 54 24
YTK 32 60
ALOE 37 57
HAL 53 39
AM-Silicon 59 50
Atlantic 24 42
ALOE 31 46
JADA 38 65
Nikit 48 49
PerKele 68 37
HAL 46 53
TOO 73 60
HAL 31 37
YTK 39 55
Nikit 57 47
FARSTIC 40 47
AM-Silicon 68 52
HAL 50 50
JADA 32 37
FRoW 47 53
SWP3 50 50
FRoW 52 52
JADA 63 58
Liquid 47 46
Drast 36 54
ALOE 44 30
HAL 39 33
Drast 48 41
SWP3 52 56
KRRAM 65 56

He tried to put the & in "A[i].costruttore, A[i].ns, A[i].costo" but it didn't work.

CodePudding user response:

Save time, enable all compiler warnings

This is the #1 lesson here.

"%d" matches a int *, not an int in fscanf()

Use the address of an int.

// fscanf(f, "%s %d %d", A[i].costruttore, A[i].ns, A[i].costo)
fscanf(f, "%s %d %d", A[i].costruttore, &A[i].ns, &A[i].costo)

Do not use "%s" without a width

Use a width 1 less than the array count.

char costruttore[20];
...
// fscanf(f, "%s %d %d", A[i].costruttore, ...
fscanf(f, "s %d %d", A[i].costruttore, ...

Do not compare against EOF

fscanf(f, "%s %d %d"... can return EOF, 1, 2, 3 (and maybe 0). Rather than test against 1 undesirable value compare against the desired result.

// while (fscanf(f, "%s %d %d", A[i].costruttore, A[i].ns, A[i].costo) != EOF)
while (fscanf(f, "%s %d %d", A[i].costruttore, A[i].ns, A[i].costo) == 3)

CodePudding user response:

As @jabberwocky noted, pointers are needed within the fscanf, however these are only needed for the costo and ns fields.

Here's an equivalent example of OPs code, with the correct structure:

#include <stdio.h>

#define DIM 100

typedef struct record {
    char f0[20];
    int f1, f2;
} record_t;

int main (void) {
    FILE *f = fopen("memory.txt", "r");
    record_t records[DIM];

    int i = 0;
    while (fscanf(f, "%s %d %d", records[i].f0, &records[i].f1, &records[i].f2) != EOF) {
        i  ;
    }

    fclose(f);
}

This runs, and produces the correct results. Without the & in front of f1 and f2, it will segfault.

  • Related