0

I am reading the following file:

records.txt:

John Smith
10
20
Michael J Smith
15
20
Glennie Macarthur
30
40
Melia Ramsburg
23
45
Wallace Weiss
49
23
Emmy Rodi
50
90
Shaunta Sinkfield
29
85
Lyndsay Riser
79
68
Leilani Weldy
14
95
Jason Roye
59
67
German Hoy
43
68
Jesse Boster
88
29

...with the code....

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

typedef struct SinglyLinkedList {
    struct SinglyLinkedList *next;
    char name[50];
    int mid;
    int final;
} SinglyLinkedList;

int tableSize;

int hashFunction(char *s) {
    int hashValue;
    for(hashValue = 0; *s != '\0'; s++) {
        hashValue += *s;
    }
    return hashValue % tableSize;
}

int main() {
    int i,j,k, found, distance, hashVal;
    SinglyLinkedList **table;
    SinglyLinkedList *temp, *ptr;
    FILE *file;
    char s[50];

    // get table size from user
    fgets(s, sizeof(s), stdin);
    sscanf(s, "%d", &tableSize);

    // initialize pointer
    table = (SinglyLinkedList**)malloc(sizeof(SinglyLinkedList*));
    for(i=0; i<tableSize; i++) {
        table[i] = NULL;
    }

    //get data from file
    file = fopen("records.txt", "r");
    while(fgets(s, sizeof(s), file) != NULL) {
        temp = (SinglyLinkedList*)malloc(sizeof(SinglyLinkedList));
        s[strlen(s)-1] = '\0';
        strcpy(temp->name, s);

        fgets(s, sizeof(s), file); sscanf(s, "%d", &(temp->mid));
        fgets(s, sizeof(s), file); sscanf(s, "%d", &(temp->final));

        hashVal = hashFunction(temp->name);

        if(table[hashVal] == NULL) {
            table[hashVal] = (SinglyLinkedList*)malloc(sizeof(SinglyLinkedList));
            strcpy(table[hashVal]->name, temp->name);
            table[hashVal]->mid = temp->mid; 
            table[hashVal]->final = temp->final;
        } else {
            ptr = table[hashVal];
            while(ptr->next != NULL) ptr = ptr->next;
            ptr->next = (SinglyLinkedList*)malloc(sizeof(SinglyLinkedList));
            strcpy(ptr->next->name, temp->name);
            ptr->next->mid = temp->mid; ptr->next->final = temp->final;
        }

        free(temp);


    } // end of while

// display whole data in Linked List
    for(i=0; i<tableSize; i++) {
        ptr = table[i];

        while(ptr != NULL) {
            printf("%d : %s, %d, %d\n", i, ptr->name, ptr->mid, ptr->final);
            ptr = ptr->next;
        }
    }

} 

The expected output is:

0 : Melia Ramsburg, 23, 45
1 : Michael J Smith, 15, 20
1 : Leilani Weldy, 14, 95
1 : Jesse Boster, 88, 29
2 : Wallace Weiss, 49, 23
2 : Shaunta Sinkfield, 29, 85
3 : John Smith, 10, 20
3 : Glennie Macarthur, 30, 40
3 : Emmy Rodi, 50, 90
3 : German Hoy, 43, 68
4 : Lyndsay Riser, 79, 68
4 : Jason Roye, 59, 67

However, if I put trailing lines of whitespace(like 10 blank lines after 29 in the end of file) at the end of the input file the following unexpected output occurs:

0 : Melia Ramsburg, 23, 45
0 : , 88, 29
0 : , 88, 29
0 : , 88, 29
1 : Michael J Smith, 15, 20
1 : Leilani Weldy, 14, 95
1 : Jesse Boster, 88, 29
2 : Wallace Weiss, 49, 23
2 : Shaunta Sinkfield, 29, 85
3 : John Smith, 10, 20
3 : Glennie Macarthur, 30, 40
3 : Emmy Rodi, 50, 90
3 : German Hoy, 43, 68
4 : Lyndsay Riser, 79, 68
4 : Jason Roye, 59, 67

What's going wrong (where does the 88 come from?) and how can I ignore blank lines in the file properly?

online.0227
  • 640
  • 4
  • 15
  • 29

1 Answers1

2

Let me explain what happened here.

When you add 10 blank lines at the end of your input file, the file becomes something like this:

// previous contents of the file
Jesse Boster
88
29
'\n'
'\n'
'\n'
'\n'
'\n'
'\n'
'\n'
'\n'
'\n'
'\n'

Then because you are reading the line and making a table record from 3 lines at a time - as a result, you are getting 3 additional record in the table (as 3*3=9; the remaining 1 line can't form a table record).

Now the answer about how 88 and 29 are inserted in the table.

You have used 3 fgets in one iteration of the while loop. The first one is to get the names - which is a string; the remaining two are for values - which are ints.

When encountering blank lines, after executing each fgets, s = "\n". For the first fgets, you manually converted s and made s = "".

But for the remaining cases, you tried to get integer from s = "\n" and failed. This resulted a garbage value getting inserted in temp->mid and temp->final; and in this case, the values are the last successful int values read from the file.

Now about ignoring blank lines in input file; you can check whether s = "\n" after fgets. Then your code will become something like this (Reference):

/* previous parts of the code */
while(fgets(s, sizeof(s), file) != NULL) {

    if(strcmp(s,"\n") == 0) // or: if(s[0] == '\n')
        continue;

    /* remaining part of the while loop */

} // end of while loop

/* remaining part of the code */
Community
  • 1
  • 1
Muntasir
  • 798
  • 1
  • 14
  • 24