在C语言I / O期间由尾随空格触发的意外输出

时间:2017-03-08 18:41:48

标签: c linked-list

我正在阅读以下文件:

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

...代码......

#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;
        }
    }

} 

预期输出为:

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

但是,如果我在输入文件的末尾放置空格的尾随行(如文件末尾29之后的10个空白行),则会发生以下意外输出:

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

出了什么问题(88来自哪里?)以及如何正确忽略文件中的空白行?

1 个答案:

答案 0 :(得分:2)

让我解释一下这里发生的事情。

当您在输入文件的末尾添加10个空行时,文件将变为如下所示:

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

然后因为你正在阅读该行并一次从3行创建一个表记录 - 结果,你在表中获得了3个额外的记录(如3*3=9;剩下的1行不能形成一张桌子记录)。

现在回答有关如何在表格中插入8829

您在fgets循环的一次迭代中使用了3 while。第一个是获取名称 - 这是一个字符串;其余两个是值 - int s。

遇到空行后,执行每个fgets后,s = "\n"。对于第一个fgets,您手动转换了s并制作了s = ""

但是对于其余的情况,您试图从s = "\n"获取整数并失败。这导致垃圾值插入temp->midtemp->final;在这种情况下,值是从文件中读取的最后一个成功的int值。

现在关于忽略输入文件中的空行;您可以在s = "\n"之后检查是否fgets。那么你的代码就会变成这样(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 */