【问题标题】:linked list: strange muddle of member element during output链表:输出时成员元素的奇怪混乱
【发布时间】:2016-02-13 12:13:13
【问题描述】:

问题陈述:给出参加某项特定调查的国家和女性和男性人数的列表。程序是从 SecondaryEd2005.txt 文件中读取列表,根据汇总的男性和女性数量对列表进行降序排序。问题必须仅使用链表解决,而不是双链表。不允许使用数组进行预排序。成员必须是:char 指向国家名称的指针,2 个 longs 代表女性和男性参与者的数量。国家名称的空间必须动态分配。输出必须采用国家名称、女性参与者人数、男性参与者人数、总和、行尾等格式。

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

#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 %d\n", cur->country, cur->females, cur->males, cur->females + cur->males);
        if (cur->link == NULL)
            break;
        cur = cur->link;
    }

    return 0;

}

如果需要任何其他信息,我可以提供。提前谢谢你。

【问题讨论】:

    标签: c linked-list dynamic-memory-allocation


    【解决方案1】:

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

    更糟糕的是,在那之后你重写了newNode-&gt;country,丢失了指向分配块的指针并设置newNode-&gt;country指向你的32字符缓冲区(所以最后country所有节点中的指针都指向同一个字符串) .应使用strncpy() or strncpy_s() 调用进行字符串复制。

    【讨论】:

      【解决方案2】:

      这里有几个错误:

          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);
      

      【讨论】:

      • 感谢您的深入解释。习惯使用c++标准库,对list的实现知之甚少。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-12
      • 1970-01-01
      • 2014-03-04
      相关资源
      最近更新 更多