链表:输出过程中成员元素的混乱

时间:2015-11-12 08:13:50

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

问题陈述:给出参与某项特定调查的国家/地区和女性和男性人数列表。程序是按照有关男性和女性总数的降序对列表进行排序,从SecondaryEd2005.txt文件中读取列表。问题必须仅使用链表解决,而不是双链表。不允许使用数组进行预分类。成员必须是:char指向国家名称,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 %d\n", cur->country, cur->females, cur->males, cur->females + cur->males);
        if (cur->link == NULL)
            break;
        cur = cur->link;
    }

    return 0;

}

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

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

你有几个错误:

<form action="#" class="input-group" data-bind="css: { focused: isPathFocused() }, submit: function(){$root.reload(true);}">
   <label for="path">Path:</label>
   <span class="prefix" data-bind="text: domain">https://www.google.com</span>
   <input type="text" id="path" name="path" data-bind="hasfocus: isPathFocused, value: path">
   <button type="submit" id="load-page-button">Load</button>
</form>
<button id="preview-toggle" class="preview-toggle-button" data-bind="attr: { title: viewState.isCollapsed() ? 'Expand preview pane' : 'Collapse preview pane' },
   click: $root.viewState.collapseOnClick,
   css: { collapsed: viewState.isCollapsed },
   text: viewState.isCollapsed() ? 'Expand' : 'Collapse'" title="Collapse preview pane">Collapse</button>
<button id="preview-toggle-close" class="preview-toggle-button" data-bind="click: $root.viewState.closeOnClick" title="Close preview pane">Close</button>

C字符串应该是NUL终止的,而<head> <script async="" src="//www.google-analytics.com/analytics.js"></script> <script type="text/javascript" async="" src="//cdn3.optimizely.com/js/geo2.js"></script> <script type="text/javascript" async="" src="https://vis.optimizely.com/api/targetingEmbed/5935064/3375340400/oeu1445896359844r0.5723679552320391"></script> <script type="text/javascript" async="" src="//cdn3.optimizely.com/js/geo2.js"></script> <script type="text/javascript" async="" src="https://optimizely.skymosity.com/sp.js?callback=optimizely_skymosity"></script> <meta charset="utf-8"> <title>Optimizely Preview</title> <link rel="stylesheet" type="text/css" href="/master-2185.388478123618610666/dist/css/preview.css"> <script src="/master-2185.388478123618610666/dist/js/preview2.js"></script><style type="text/css"></style> <script type="text/javascript" src="//cdn.optimizely.com/js/5935064.js"></script> <script src="https://odds.optimizely.com/js/geo2.js?c__mkto_trk=id%3A361-GER-922%26token%3A_mch-optimizely.com-1445896362127-52041&amp;project=5935064" type="text/javascript"></script> <script src="https://vis.optimizely.com/api/targetingEmbed/5935064/3375340400/oeu1445896359844r0.5723679552320391" type="text/javascript"></script> <iframe src="https://5935064.cdn.optimizely.com/client_storage/5935064.html"></iframe> </head> 并不能解释这一点。也许在这里使用 n = strlen(c); newNode->country = malloc(n*sizeof(char)); newNode->country = c; 会更好:

strlen()

当您拆除列表时,您仍然需要strdup()内存。

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

    newNode->county = strdup(c);

将country设置为指向堆栈上的缓冲区,该缓冲区将消失,指针指向无效内存 - 或者更糟糕的是,有效内存不是您自己的内存。至少,对于扫描的每一行,它都会被破坏,这使得所有节点都指向最后读取的国家/地区。如果您要坚持分配自己的记忆,那应该更像是:

free()