我正在尝试从.txt文件中读取一堆名称,然后将它们复制到数组中。然后我想使用qsort()对数组进行排序。另外,我正在阅读的文件是来自Project Euler #22的names.txt。这是代码:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
/* create a pointer to point to s */
char *strdup(char *s)
{
char *p;
p = (char *) malloc(strlen(s)+1);
if (p != NULL)
strcpy(p, s);
return p;
}
int compare(const void *a, const void *b)
{
const char *ap = *(const char **) a;
const char *bp = *(const char **) b;
return strcmp(ap, bp);
}
int main(void)
{
FILE *fp;
int c, i, j=0;
char name[100], *names[10000];
fp = fopen("names.txt", "r");
if (fp == NULL) {
printf("can't open file\n");
exit(0);
}
c = fgetc(fp); /* initialize c and skip first quotation mark */
while (c != EOF) { /* loop until no names are left */
i = 0;
while ((c=fgetc(fp)) != '"') /* copy chars to name until " is reached */
name[i++] = c;
name[i] = '\0';
names[j++] = strdup(name);
fgetc(fp); /* skip comma */
c = fgetc(fp);
}
size_t size = sizeof(names[0]);
size_t count = sizeof(names)/size;
qsort((void **) names, count, size, &compare);
return 0;
}
尝试对names数组进行排序会导致段错误。但是,如果我尝试对显式声明的字符串数组进行排序,那么它可以工作:
char *test[] = { "FOO", "BAR", "TEST" };
size_t size = sizeof(test[0]);
size_t count = sizeof(test)/size;
qsort((void **) test, count, size, &compare);
for (i = 0; i < 3; ++i)
printf("%s\n", test[i]);
return 0;
我怀疑segfault是由于我的数组“名称”中的错误引起的,但如果我在尝试排序之前遍历并打印“names”的每个元素,那么就没有问题。
非常感谢任何帮助!
答案 0 :(得分:3)
这一行:
size_t count = sizeof(names)/size;
将产生names
数组的整个长度,而不仅仅是您初始化的值。如果您输入的名称少于10000个,那么您将会在其中输入一些无效指针,当您尝试对它们进行排序时 - KABOOM!
您可以使用j
代替count
,因为您正在使用它来跟踪已输入的名称数。
答案 1 :(得分:0)
您缺少初始化names
。
最简单的方法就是这样:
names[10000] = {NULL};
比较函数也没有准备好处理未使用的条目,您可以像这样修改它,处理未使用的条目,如emtpy条目。
int compare(const void *a, const void *b)
{
const char *ap = a ?*(const char **) a :"";
const char *bp = b ?*(const char **) b :"";
return strcmp(ap, bp);
}
另外,您可以将所有未使用的条目排序到最后:
int compare(const void *a, const void *b)
{
if (*a && *b)
{
const char *ap = a ?*(const char **) a :"";
const char *bp = b ?*(const char **) b :"";
return strcmp(ap, bp);
}
else
{
if (*a)
return -1;
else (*b)
return 1;
return 0;
}
}
此外,您告诉qsort()
始终检查所有names
条目。这是不必要的。