链表:输出时成员元素出现奇怪的混乱
linked list: strange muddle of member element during output
问题陈述:给定一份国家名单以及参与某项特定调查的女性和男性人数。程序是根据汇总的男性和女性数量对列表进行降序排序,从 SecondaryEd2005.txt 文件中读取列表。问题必须只使用链表来解决,而不是双链表。不允许使用数组进行预排序。成员必须是:指向国家名称的 char 指针,2 longs 表示女性和男性参与者的数量。 Space 必须动态分配国家名称。输出必须采用国家名称、女性参与者人数、男性参与者人数、总和、行尾等格式。
问题:在任何情况下,代码都会输出最后读取的国家/地区名称,同时正确输出有关男性和女性的数量及其总和,它们按降序排列。我试图在将新节点放入列表的正确位置之前输出新节点的成员,它给出了正确的输出,表明所有内容都已正确读取。
我认为有些东西的国家名称是动态分配的,但不确定,如果它是正确的,不知道到底是什么。这是代码:
#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;
}
如果需要任何其他信息,我可以提供。提前谢谢你。
strlen() returns 字符串长度 没有 空终止符。这很重要(基本上你想要 newNode->country = malloc(n+1);
,sizeof(char)
总是 1)。
更糟糕的是,在那之后你重写了 newNode->country
,丢失了指向已分配块的指针并设置 newNode->country
指向你的 32 字符缓冲区(所以最后 country
中的指针所有节点都指向同一个字符串)。应使用 strncpy() or strncpy_s() 调用进行字符串复制。
你这里有几个错误:
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);
问题陈述:给定一份国家名单以及参与某项特定调查的女性和男性人数。程序是根据汇总的男性和女性数量对列表进行降序排序,从 SecondaryEd2005.txt 文件中读取列表。问题必须只使用链表来解决,而不是双链表。不允许使用数组进行预排序。成员必须是:指向国家名称的 char 指针,2 longs 表示女性和男性参与者的数量。 Space 必须动态分配国家名称。输出必须采用国家名称、女性参与者人数、男性参与者人数、总和、行尾等格式。
问题:在任何情况下,代码都会输出最后读取的国家/地区名称,同时正确输出有关男性和女性的数量及其总和,它们按降序排列。我试图在将新节点放入列表的正确位置之前输出新节点的成员,它给出了正确的输出,表明所有内容都已正确读取。 我认为有些东西的国家名称是动态分配的,但不确定,如果它是正确的,不知道到底是什么。这是代码:
#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;
}
如果需要任何其他信息,我可以提供。提前谢谢你。
strlen() returns 字符串长度 没有 空终止符。这很重要(基本上你想要 newNode->country = malloc(n+1);
,sizeof(char)
总是 1)。
更糟糕的是,在那之后你重写了 newNode->country
,丢失了指向已分配块的指针并设置 newNode->country
指向你的 32 字符缓冲区(所以最后 country
中的指针所有节点都指向同一个字符串)。应使用 strncpy() or strncpy_s() 调用进行字符串复制。
你这里有几个错误:
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);