Search code examples
clinked-listscanffgets

Reading dates from file to linked list


void readDataFromFile(President **h) {
    FILE *fp = fopen("President.txt", "r");
    if (fp == NULL) {
        printf("Cannot open a file!\n");
        return;
    }

    char buffer[MAX];
    int rno, start_date, end_date;
    char name[MAX];

    while(fgets(buffer, MAX, fp) != NULL) {
        // Reading data from line
        if (sscanf(buffer, "%d %[^\n] %d-%d", &rno, name, &start_date, &end_date) != 4) {
            printf("Error trying to read file!\n");
            fclose(fp);
            return;
        }

        // Creating of new node
        President *newNode = (President*)malloc(sizeof(President));
        if (newNode == NULL) {
            printf("Memory error!\n");
            fclose(fp);
            return;
        }
        newNode->rno = rno;
        strcpy(newNode->name, name);
        newNode->start_date = start_date;
        newNode->end_date = end_date;
        newNode->next = NULL;

        // Adding new node to list
        if (*h == NULL) {
            *h = newNode;
        } else {
            President* current = *h;
            while (current->next != NULL) {
                current = current->next;
            }
            current->next = newNode;
        }
    }

    fclose(fp);
    printf("Data is added to list!\n");
}

Hello. I'm trying to read from file to linked list , but i always get an error cause of if(sscanf). What is wrong with my code? I've checked several time the text inside the file but its ok , but anyway cant read it.Can i have some help or maybe some useful links? I'm ready to manage it by myself if you show where i can read about it.

Here are three sample lines from the input file

1 President 2000-2004 
2 President 1932-1957 
3 President 2012-2016

Solution

  • My testing of your code reveals that the regular expression %[^\n] consumes the rest of the line, leaving nothing for variables start_date and end_date, and is very likely root cause of the issue.

    I suggest this regular expression: %[^ ] -- which will stop scanning at the first white space:

    sscanf(buffer, "%d %[^ ] %d-%d", &rno, name, &start_date, &end_date)
    

    If there are 2 names separated by space, you might do this to address that scenario -- please keep in mind that successful sscanf() should return 5 in this example:

    sscanf(buffer, "%d %[^ ] %[^ ] %d-%d", &rno, fname, lname, &start_date, &end_date)
    

    NOTE: @Weather Vane very kindly pointed out that %s will work in place of %[^ ]. Yes, of course! (Thanks again).

    All suggestions tested successfully on data file having this format... showing version 2 (first name + last name):

    1 First Last 1933-1944
    2 First Last 1944-1948
    ...
    ...