Search code examples
clistcrashdynamic-memory-allocation

Loading file into linked list on C, sometimes works, sometimes doesnt


This is the function I use to load it, sometimes it works but when I leave the program and compile again, it will just crash:

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

//this is how I declared the list
struct plantillas {
    int iduser;
    int idplant;
    char name[31];
    int pres;
    int punt;
    struct plantillas *next;
};
struct plantillas *first, *last;

//This is the main that calls loadfile:
int main(){
    FILE *file;
    file = fopen("Plantillas.txt", "r");
    puts("a");
    load_file(file);
    fclose(file);
}

//this is the funcion that actually loads the file
void load_file(FILE *file) {
    char cadaux[100];
    first = (struct plantillas *) NULL;
    last = (struct plantillas *) NULL;
    struct plantillas *new;

    while (!feof(fichero)){
        /* save memory for the new element on the list */
        new = (struct plantillas *) malloc(sizeof(struct plantillas));
        if (new == NULL) printf("No memory avaiable!\n");
        fflush(stdout);

        readline(file, cadaux); //I'll explain about this later
        sscanf(cadaux, "%d %d %s %d   %d", &new->iduser, &new->idplant, new->name, &new->pres, &new->punt);

        new->next = NULL;

        /* this will find out if the linked list is empty or not */
        if (first == NULL) {
            first = new;
            last = new;
        }
        else {
            /* if it isn't, the one that was last before now has to point to the next element on the list */
            last->next = new;
            /* now we make the new be the last */
            last = new;
        }
    }
}

/*The readline function is because of format issues. As it is an    assignment for school, the format of the file has to be in1-int2- string1-int3-int4, readline reads each line on the file and turn the '-' into ' ' and then saves it into an auxiliary string. Here is the function:*/

void readline(FILE * a, char * b)
{
    int i;
    fscanf(a, "%s", b);
    for (i = 0; b[i] != '\n'; i++)
    {
        if (b[i] == '-') b[i] = ' ';
    }
}

Sorry if there are some variables that doenst match at all, I translated the code from spanish to try make it more understandable. Also, sorry for the formating issues, its my first post here and I had some trouble


Solution

  • There are two major errors in your code that will cause problems.

    The first is that you should not do while (!feof(...)), because the EOF flag is not set until you try to read from beyond the file, causing the loop to iterate once to many. This is bad but not fatal, because all it does is cause you to add an extra node last with dummy data.

    The second and absolutely fatal error is that you use fscanf to read a string which doesn't contain a newline (or any white-space at all), and then you look for a newline while writing to the buffer. Because the string you read will not contain a newline, the loop after fscanf will go beyond the end of the buffer, and you will most likely write to data somewhere on the stack leading to undefined behavior. The correct condition for that loop would be to look for the string terminator '\0'.


    My suggestion to solve both of these problems is to not have a readline function, and to use fgets instead, and use while (fgets(cadaux, sizeof(cadaux), file) != NULL) as loop condition, and a function to replace the '-' characters with spaces, and in that function check for both newline and the string terminator in the loop.