链表:输出时成员元素的奇怪混乱



问题陈述:列出参与某项特定调查的国家和女性人数。程序是按照男性和女性总数的降序对列表进行排序,读取SecondaryEd2005.txt文件中的列表。问题只能使用链表来解决,而不能使用双链表。不允许使用数组进行预排序。成员必须是:字符指针指向国家名称,2长代表女性和男性参与者的数量。国家名称的空间必须动态分配。输出的格式必须像国家名称、女性参与者人数、男性参与者人数、他们的总和、行的末尾。

问题:在任何情况下,代码都会输出读取的最后一个国家名称,而它会正确输出男性和女性的数量及其总和,它们是按降序排列的。我试图在新节点被放在列表的正确位置之前输出它的成员,它给出了正确的输出,表明所有内容都被正确读取。我认为国家名称是动态分配的,但不确定,如果它是正确的,不知道具体是什么。这是代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct _person_count {
    char* country;
    long females;
    long males;
    struct _person_count *link;
} person_count;
int main () {
    FILE *file;
    file = fopen("SecondaryEd2005.txt","r");
    person_count *first = NULL;
    char c[32];
    int male;
    int female;
    do {
        person_count *newNode = malloc(sizeof(person_count));
        fscanf(file, "%s %i %i %i", c, &female, &male);
        newNode->females = female;
        newNode->males = male;
        int n;
        n = strlen(c);
        newNode->country = malloc(n*sizeof(char));
        newNode->country = c;
    newNode->link = NULL;
        printf("still reading: %s %i %i n", newNode->country, newNode->females, newNode->males);
        if(first == NULL) {
            first = newNode;
        } else {
            int sumnewNode = newNode->females + newNode->males;
            int sumFirst = first->females + first->males;
            if(sumnewNode > sumFirst) {
                newNode->link = first;
                first = newNode;
            }else {
                person_count* current = first;
                while (1)
                {
                    if (current->link == NULL)
                    {
                        current->link = newNode;            
                        break;
                    }
                    else if (current->link->females + current->link->males < sumnewNode)
                    {
                        newNode->link = current->link;
                        current->link = newNode;
                        break;
                    }
                    current = current->link;
                }
            }
        }
    } while(!feof(file));

    person_count* cur = first;
    while(1)
    {
    printf("%s %d %d %dn", cur->country, cur->females, cur->males, cur->females + cur->males);
        if (cur->link == NULL)
            break;
        cur = cur->link;
    }
    return 0;
}

如果需要任何额外的信息,我可以提供。提前谢谢。

这里有几个错误:

    n = strlen(c);
    newNode->country = malloc(n*sizeof(char));
    newNode->country = c;

C字符串应该以NUL结尾,而strlen()没有考虑到这一点。也许在这里使用strdup()会更好:

    newNode->county = strdup(c);

以后当您拆下列表时,您仍然需要free()内存。

此外,您的版本会泄漏内存,因为您从未实际使用过分配的缓冲区。此行:

    newNode->country = c;

将country设置为指向堆栈上的缓冲区,该缓冲区将消失,使指针指向无效内存,或者更糟的是,指向不是您自己的有效内存。至少,扫描的每一行都会被打得落花流水,这使得你的所有节点都指向最后一个国家。如果你要坚持分配自己的内存,它应该更像:

    newNode->country = calloc((n+1) * sizeof(char));
    strncpy(newNode->country, c, n);

strlen()返回不带null终止符的字符串长度。这很重要(基本上你想要newNode->country = malloc(n+1);sizeof(char)总是1)。

更糟糕的是,在重写newNode->country之后,会丢失指向已分配块的指针,并将newNode->country设置为指向32个字符的缓冲区(因此最终所有节点中的country指针都指向同一个字符串)。应使用strncpy()或strncpy_s()调用进行字符串复制。

最新更新