Akiyuu
Akiyuu

Reputation: 33

C: Newbie attemping file reading and struct allocation using malloc

I am trying to store the values stored in a details.txt file into their appropriate place in a dynamically allocated struct. Am I doing something (that should be simple) incorrectly for this not to work? Is it necessary for me to use strtok and split by ','?

My details.txt reads:

mitch,8,1.78,burgers

murray,42,6.5,lasagna

travis,64,1.85,sushi

sam,12,1.94,bacon

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BUFFERSIZE 256

typedef struct 
{
    char name[BUFFERSIZE];
    int favnumber;
    float height;
    char favfood[BUFFERSIZE];
} Person;

void print_person(Person *p) 
{
    printf("name: %s\n", p->name);
    printf("num: %d\nheight: %.2f\nfav. food: %s\n\n",
        p->favnumber, p->height, p->favfood);
}

int count_lines(FILE *fp) 
{
    int nlines = 0;
    char c;
    for (c = fgetc(fp); c != EOF; c = fgetc(fp)) 
    {
        if (c == '\n') 
        {
            nlines++;
        }
    }
    rewind(fp);
    return nlines;
}

int main(void) 
{
    FILE *fp = fopen("details.txt", "r");
    
    // count lines
    int nlines = count_lines(fp);
    printf("found %d lines\n\n",nlines);

    Person *people = (Person*)malloc(nlines*sizeof(Person));

    char buffer[BUFFERSIZE];
    int i = 0;
    while (fgets(buffer,BUFFERSIZE,fp) != NULL) 
    {
        sscanf(buffer,"%s%d%f%s",people[i].name,
            &(people[i].favnumber),
            &(people[i].height),people[i].favfood);
        print_person(&(people[i]));
        i++;
    }
    printf("found %d people\n",i);

    free(people);

    fclose(fp);
}

Unfortunately, the current output of my program is:

found 4 lines

name: mitch,8,1.78,burgers

num: 0

height: 0.00

fav. food:

...

found 4 people

Upvotes: 0

Views: 43

Answers (1)

user9706
user9706

Reputation:

The problem is that the first %s parse the the whole line, and you need , in the format string to separate the fields. Not an issue here yet but I also used %[^,] for the last format string so it will not stop at the first space. Also added precision on the strings to avoid buffer overflows:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BUFFERSIZE 255
#define str(s) str2(s)
#define str2(s) #s

typedef struct 
{
    char name[BUFFERSIZE+1];
    int favnumber;
    float height;
    char favfood[BUFFERSIZE+1];
} Person;

void print_person(Person *p) 
{
    printf("name: %s\n", p->name);
    printf("num: %d\nheight: %.2f\nfav. food: %s\n\n",
        p->favnumber, p->height, p->favfood);
}

int count_lines(FILE *fp) 
{
    int nlines = 0;
    char c;
    for (c = fgetc(fp); c != EOF; c = fgetc(fp)) 
{
        if (c == '\n') {
            nlines++;
        }
    }
    rewind(fp);
    return nlines;
}

int main(void) 
{
    FILE *fp = fopen("details.txt", "r");

    // count lines
    int nlines = count_lines(fp);
    printf("found %d lines\n\n",nlines);

    Person *people = (Person*)malloc(nlines*sizeof(Person));

    char buffer[BUFFERSIZE+1];
    int i = 0;
    while (fgets(buffer,BUFFERSIZE+1,fp) != NULL) 
{
// Changed line, see formatting of %s
        sscanf(buffer,
            "%" str(BUFFERSIZE) "[^,],%d,%f,%" str(BUFFERSSIZE) "[^,]",
            people[i].name,
            &(people[i].favnumber),
            &(people[i].height),people[i].favfood);
        print_person(&(people[i]));
        i++;
    }
    printf("found %d people\n",i);

    free(people);

    fclose(fp);
}

Upvotes: 2

Related Questions