0

This is my C code. First of all, I created struct data and then read a binary file, but my fscanf function does not correctly work. I'm getting a segmentation fault.

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

#define DATA_FILE "records.dat"

struct record
{
    char name[64];
    char surname[64];
    char gender;
    char email[32];
    char phone_number[16];
    char address[32];
    char level_of_education[8];
    unsigned int income_level;
    unsigned int expenditure;
    char currency_unit[16];
    char currentModd[32];
    float height;
    unsigned int weight;
};
typedef struct record myrecord;

int main()
{
    myrecord rItem;
    FILE *fp;
    struct record Myrecord;
    if ((fp = fopen(DATA_FILE, "r")) != NULL)
    {
        fscanf(fp, "%s %s %s %s %s %s %s %d %d %s %s %f %d\n", &rItem.name, &rItem.surname, &rItem.gender, &rItem.email,
               &rItem.phone_number, &rItem.address, &rItem.level_of_education, &rItem.income_level, &rItem.expenditure,
               &rItem.currency_unit, &rItem.currentModd, &rItem.height, &rItem.weight
        );
        printf("doneeee");
    }
    else
    {
        printf("errorrrr ");
    }
}

And my output is like this:

Segmentation fault

[Done] exited with code=139 in 0.17 seconds

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
normin48
  • 15
  • 4
  • 1
    You can't use the `%s` format specifier to read in a *single* `char` variable, as you are attempting to do with the `&rItem.gender` argument. Not sure if that's the only issue, though, as you talk of reading a "binary file" but `fscanf` is for **text**-mode input. The fix depends on what you want the `gender` field to be: a single character (then use `%c`) or a null-terminated string (then it needs to be an array of `char`, like the other fields). – Adrian Mole May 11 '21 at 23:09
  • 1
    Remove `&` from array assignments. You don't need to pass a pointer for what is already a pointer. – Alex Reynolds May 11 '21 at 23:14
  • 1
    Also, use `%u` for *unsigned* integers - `%d` is for *signed* arguments. – Adrian Mole May 11 '21 at 23:15
  • 1
    Never use `%s`. Always add a maximum field width that is at most 1 less than the size of the buffer that will be written to. eg `fscanf(fp,"%63s %63s ...` When you consider that `gender` is size 1, you may be tempted to use the format string `%0s` which should indicate that something is wrong. – William Pursell May 11 '21 at 23:23
  • You should also examine the return value of f/s scanf family of functions. – hetepeperfan May 12 '21 at 09:48
  • I did everything but it still doesnt work. – normin48 May 12 '21 at 14:09

2 Answers2

0

Try without the & at the string values in your scanf. Your variable „name“ for example. Writing it without [] already means it is a pointer to the first character of your array. By writing &name you would point to the pointer.

guest
  • 9
  • 1
0

The suggestions so far have said:

  1. remove "&" in front of "string" variables in the fscanf() call.
  2. change "%d" to "%u" as the specifier for "unsigned int" variables in fscanf() call
  3. change "%s" to "%c" as the specifier for the "char" (not char [] ) variables in fscanf() call
  4. add length specifier to "%s" in fscanf() call

Note: you did not show the contents of "records.dat" file, which could not match the specifications.

And yet you say you've made the changes and still get a segmentation fault.

Lets assume this is your "records.dat" file (just one line):

<-my_name-> <-sir_name-> M <-email-> <-phone-> <-address-> <-levl-> 50000 5000 <-mon-unit-> <-currMODD-> 14.5 250

Here is an example of all of the above modifications (except #4) to your code, and which also prints out the results of fscanf(). It also contains your original code, commented out. This does not segv when tested against my "records.dat". I leave it to you to integrate the #4 suggestion, and test it on your version of records.dat.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DATA_FILE "records.dat"
 struct record {
    char name[64];
    char surname[64];
    char gender;
    char email[32];
    char phone_number[16];
    char address[32];
    char level_of_education[8];
    unsigned int income_level;
    unsigned int expenditure;
    char currency_unit[16];
    char currentModd[32];
    float height;
    unsigned int weight;
 };
typedef struct record myrecord;
int main()
{
    myrecord rItem;
    FILE *fp;
    struct record Myrecord;
    if ((fp = fopen(DATA_FILE,"r")) !=NULL)
    {
        /* ORIG:  fscanf(fp,"%s %s %s %s %s %s %s %d %d %s %s %f %u\n",
          &rItem.name,               // 1
          &rItem.surname,            // 2
          &rItem.gender,             // 3  - char
          &rItem.email,              // 4
          &rItem.phone_number,       // 5
          &rItem.address,            // 6
          &rItem.level_of_education, // 7
          &rItem.income_level,       // 8  - unsigned int
          &rItem.expenditure,        // 9  - unsigned int
          &rItem.currency_unit,      // 10
          &rItem.currentModd,        // 11
          &rItem.height,             // 12 - float
          &rItem.weight);            // 13 - unsigned int
     */
              //   1  2  3  4  5  6  7  8  9  10 11 12 13
        fscanf(fp,"%s %s %c %s %s %s %s %u %u %s %s %f %u\n",
           rItem.name,               // 1
           rItem.surname,            // 2
          &rItem.gender,             // 3  - char
           rItem.email,              // 4
           rItem.phone_number,       // 5
           rItem.address,            // 6
           rItem.level_of_education, // 7
          &rItem.income_level,       // 8  - unsigned int
          &rItem.expenditure,        // 9  - unsigned int
           rItem.currency_unit,      // 10
           rItem.currentModd,        // 11
          &rItem.height,             // 12 - float
          &rItem.weight);            // 13 - unsigned int
        printf("doneeee\n");
    printf("name:     %s\n"
           "surname:  %s\n"
           "gender:   %c\n"
           "email:    %s\n"
           "phone:    %s\n"
           "address:  %s\n"
           "ed_level: %s\n"
           "incm_lvl: %u\n"
           "expend:   %u\n"
           "CurrUnit: %s\n"
           "CurrModd: %s\n"
           "height:   %f\n"
           "weight:   %u\n",
           rItem.name,               // 1
           rItem.surname,            // 2
           rItem.gender,             // 3  - char
           rItem.email,              // 4
           rItem.phone_number,       // 5
           rItem.address,            // 6
           rItem.level_of_education, // 7
           rItem.income_level,       // 8  - unsigned int
           rItem.expenditure,        // 9  - unsigned int
           rItem.currency_unit,      // 10
           rItem.currentModd,        // 11
           rItem.height,             // 12 - float
           rItem.weight);            // 13 - unsigned int

    }
    else{
        printf("errorrrr ");
    }
    
    
}
TonyB
  • 927
  • 6
  • 13