Search code examples
cfilefopenfclose

C - Opening differents files using same pointer


I'm trying to retrieve informations by many plain-text files, which will be then stored in a proper struct. To do so, I'm using a function that takes member of the struct to populate and source of the plain-text file where the informations are stored.

Posting my "test" code:

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

struct _elem
{
    const char *title;
    int ok;
    int almost;
    int nope;
    int hits;
    float last_rank;
};

typedef struct _elem Chapter;

Chapter *generate_array(const char *source, int *elems);
int engine_start(Chapter *elem, char *source);

int main()
{
    const char path_f[100];
    int elements = 0;
    int i = 0;

    Chapter *dict;

    printf("Insert the name of the source:\n");
    scanf("%s", path_f);

    printf("\nGenerating dictionary, please wait...\n");
    dict = generate_array(path_f, &elements);

    if (dict == NULL)
    {
        printf("Aborting.\n");
        exit(1);
    }

    while (i < elements)
    {
        printf("Element %d:\n", (i + 1));
        printf("\nTitle: %s\n", dict[i].title);
        printf("Ok: %10d\n", dict[i].ok);
        printf("Almost: %5d\n", dict[i].almost);
        printf("Nope: %8d\n", dict[i].nope);
        printf("Hits: %8d\n", dict[i].hits);
        printf("Rank: %8.2f\n", dict[i].last_rank);
        printf("\n");
        i++;
    }

    return EXIT_SUCCESS;
}

Chapter *generate_array(const char *source, int *elems)
{
    FILE *src;

    int sources;
    int i = 0;

    char **srcs;

    Chapter *generated;

    src = fopen(source, "r");

    if (src == NULL)
    {
        printf("[!!] Error while reading file!\n");
        return NULL;
    }

    fscanf(src, "%d", &sources);

    if (sources <= 0)
    {
        printf("[!!] Wrong number of sources, exiting.\n");
        return NULL;
    }

    srcs = (char **) malloc(sizeof(char *) * sources);

    while (i < sources && !feof(src))
    {
        srcs[i] = (char *) malloc(sizeof(char) * 100);
        fscanf(src, "%s", srcs[i++]);
    }

    fclose(src);

    generated = (Chapter *) malloc(sizeof(Chapter) * i);
    *elems = i;
    i = 0;

    while (i < *elems)
    {
        if(engine_start( &generated[i], srcs[i] )) i++;
        else
        {
            printf("[!!] Error in file %s, aborting.\n", srcs[i]);
            return NULL;
        }
    }

    return generated;
}

int engine_start(Chapter *elem, char *source)
{
    FILE *parser;
    int done = 0;

    parser = fopen(source, "r");

    if (parser == NULL) printf("[!!] Error while opening %s, aborting.\n", source);
    else
    {
        fgets(elem->title, 100, parser);
        fscanf(parser, "%d %d %d %d %f", &(elem->ok),   &(elem->almost),
                                         &(elem->nope), &(elem->hits),
                                         &(elem->last_rank) );

        fclose(parser);
        done = 1;
    }

    return done;
}

Now this is the main file where are stored paths to the other plain-text files: lol.dat

5
lold/lol1.dat
lold/lol2.dat
lold/lol3.dat
lold/lol4.dat
lold/lol5.dat

And one example of lolX.dat:


Qual'è la vittoria di cristo?
3 4 5 12 44.9

I'm getting SIGSEGV after the first iteration of "engine_start", probably due to FILE *parser (but I can be totally wrong, I don't know at this point).

Someone can guide me through this problem? Thank you.


Solution

  • Make the following changes and try-

    struct _elem
    {
    char *title; // allocate the memory for this.
    int ok;
    int almost;
    int nope;
    int hits;
    float last_rank;
    };
    

    You need to allocate memory for element title before assigning something to it.

    int engine_start(Chapter *elem, char *source)
    {
    FILE *parser;
    int done = 0;
    
    parser = fopen(source, "r");
    
    if (parser == NULL) printf("[!!] Error while opening %s, aborting.\n", source);
    else
    {
        elem->title=(char *)malloc(100);  // include this line.
        fgets(elem->title, 100, parser);
        fscanf(parser, "%d %d %d %d %f", &(elem->ok),   &(elem->almost),
                                         &(elem->nope), &(elem->hits),
                                         &(elem->last_rank) );
    
        fclose(parser);
        done = 1;
    }
    
    return done;
    }