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

标签 c linked-list

我正在阅读以下文件:

记录.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 来自哪里?)以及如何正确忽略文件中的空行?

最佳答案

让我解释一下这里发生了什么。

当您在输入文件末尾添加 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 的答案。

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

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

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

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

关于c - C 语言 I/O 期间由尾随空格触发的意外输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42679391/

相关文章:

c - 链接列表更改

c - 在链表中搜索字符串并获取所有变量

c - 单线程程序是否在多个线程上执行? [C]

C 编程调用函数...将 (float*)X 传递给函数

c - 使用 fread 的初始结构数组

c - 结构效率

java - 帮助处理双向链接循环列表

C++ 链表仅在 GNU/Linux 而不是 Windows 中导致段错误

c - 为什么 qsort 需要 4 个字节来对字符串文字进行排序?

c++ - std::vector<std::string> 到 char* 数组