Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C Programming: Reading a file and storing in array of struct

I am trying to read a file test.txt via fscanf and store it in a array of struct. This is what I tried. Problem here is that fscanf is not working as it is supposed to. After reading the file, I am also trying to print it on screen, but it won't work.

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

struct Item {
   double value;
   int unit;
   char name[50];
};

int load(struct Item* item, FILE* data);
void display(struct Item item, int variableA);

int main()
{
  struct Item I;
  int i;
  char ck;
  ck =  fopen("test.txt", "r");
  if (ck)
  {
    for (i = 0; i < 3; i++)
    {
        load(&I, ck);
        display(I, 0); //DISPLAY FUNCTION THAT READS test.txt and DISPLAYS
    }
    fclose(ck);
  }
return 0;
}


int load(struct Item* item, FILE* data)
{
    fscanf(data, "%d,%.2lf,%s\n", &(*item).unit,&(*item).value,&(*item).name);
    return 0;
}

void display(struct Item item, int variableA)
{
printf("|%3d |%12.2lf| %20s |***\n", item.unit, item.value, item.name);
return;
}

This is what I have in test.txt file:

205,11.20,John Snow
336,23.40,Winter is coming
220,34.20,You know nothing

Error: Program compiles with some warnings , but I get segmentation fault when I execute the code.

Any idea why?

Output Expectation: OUTPUT should be read from test.txt file and should be displayed on to the screen.

like image 428
John Avatar asked Dec 04 '25 11:12

John


1 Answers

Multiple problems in the program:

1.

char ck;
ck =  fopen("test.txt", "r");

fopen returns a FILE*, not a char, use

FILE* ck = fopen(...);

2.

fscanf(data, "%d,%.2lf,%s\n", &(*item).unit,&(*item).value,&(*item).name);

always check return value of fscanf, if it is smaller than the number of fields you requested, the following call to fscanf is unlikely to do what you expect. Also, *item.unit is the same as item->unit, use item->unit because it is shorter and cleaner:

int ret = fscanf(data, "%d,%lf,", &item->unit, &item->value);
if (ret != 3) { // error }

Third, %s matches a sequence of non-white-space characters, so when fscanf reads "John", it will stop, and the next fscanf call will get to read "Snow" while expecting an integer.

So to input a string with whitespace, use fgets instead, and remember to remove the newline character in the end.

Try following:

int main(void)
{
    struct Item I;
    int i;
    FILE* ck;
    int ret;
    ck =  fopen("test.txt", "r");
    if (ck)
    {
            for (i = 0; i < 3; i++)
            {
                    ret = load(&I, ck);
                    if (ret < 0)
                            break;
                    display(I, 0); //DISPLAY FUNCTION THAT READS test.txt and DISPLAYS
            }
            fclose(ck);
    }
    return 0;
}

int load(struct Item* item, FILE* data)
{
    int ret = fscanf(data, "%d,%lf,", &item->unit, &item->value);
    if (ret != 2) {
            return -1;
    }
    fgets(item->name, sizeof item->name, data);
    item->name[strlen(item->name)-1] = '\0';
    return 0;
}

void display(struct Item item, int variableA)
{
    printf("|%3d |%12.2lf| %20s |***\n", item.unit, item.value, item.name);
    return;
}

It outputs:

$ ./a.out
|205 |       11.20|            John Snow |***
|336 |       23.40|     Winter is coming |***
|220 |       34.20|     You know nothing |***
like image 63
fluter Avatar answered Dec 07 '25 01:12

fluter



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!