问题陈述:列出参与某项特定调查的国家和女性人数。程序是按照男性和女性总数的降序对列表进行排序,读取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()调用进行字符串复制。