c - qsort 段错误结构

标签 c arrays struct segmentation-fault segment

所以,我的第一个问题,请耐心等待:

我的任务是对结构数组(名字、姓氏和另一个生日结构,由年、月、日组成)进行排序。我必须按生日排序并使用 qsort。 我的问题是,我查阅了有关 qsort 的所有内容,但我不太确定我的实现是否正确,因为我是 C 的新手。我可以创建可执行程序,但它不会只给我任何结果段错误。

这是我的代码:

#include <stdio.h>
#include <stdlib.h>

typedef int (*compfn) (const void*, const void*);

typedef struct {
    unsigned year, month, day;
} date_t;

typedef struct {
    char name[32];
    char surname[32];
    date_t birthday;
}person_t;

typedef struct {
    unsigned n;
    unsigned cap;
    person_t *arr;
} persons_t;


int compare(person_t *a, person_t *b){
  if(a->birthday.year!=b->birthday.year){
    return a->birthday.year-b->birthday.year;
  }else{
    if(a->birthday.month!=b->birthday.month){
      return a->birthday.month-b->birthday.month;
    }else{
      return a->birthday.day-b->birthday.day;
    }
  }
}

int main(int argc, char* argv[])
{
    if (argc <= 1) {
        fprintf(stderr, "syntax: %s <inputfile>\n", argv[0]);
        return 1;
    }

    FILE* f = fopen(argv[1], "rt");
    if (f == NULL) {
        fprintf(stderr, "cannot open file %s\n", argv[1]);
        return 1;
    }

    persons_t persons;
    persons.n = 0;
    persons.cap = 0;
    persons.arr = NULL;

    person_t p;
    while (fscanf(f, "%s %s %4u-%2u-%2u", p.name, p.surname,
            &p.birthday.year, &p.birthday.month, &p.birthday.day) == 5) {

        if (persons.n == persons.cap) {
            persons.cap = persons.cap == 0 ? 1 : 2 * persons.cap;
            persons.arr = realloc(persons.arr, persons.cap * sizeof(persons.arr[0]));
        }

        persons.arr[persons.n++] = p;
    }

    int nitems = persons.cap*sizeof(persons.arr[0]);
    int size = sizeof(persons.arr[0]);
    qsort(persons.arr, nitems, size, (compfn)compare);
    for (unsigned i = 0; i < persons.n; i++) {
        person_t *p = persons.arr + i;
        printf("%s %s %4u-%2u-%2u\n",
                p->name, p->surname,
                p->birthday.year, p->birthday.month, p->birthday.day);
    }



    fclose(f);
    return 0;
}

希望有人能帮帮我, 提前致谢;)

最佳答案

至于_t - 后缀的标识符,根据 C 标准,它们是为实现保留的(例如,您的编译器和/或您的标准库)。您的实现很可能已经有一个 date_t类型,您的代码可能会引起某种恶作剧。如果您希望避免微妙而危险的标识符冲突造成各种破坏,最好避免它们。不用担心,您始终可以使用 ' _s ' 表示 struct改为输入!


每当您声明一个表示数组中的索引的变量时,请使用 size_t作为类型!


int compare(person_t *a, person_t *b){

...

qsort(persons.arr, nitems, size, (compfn)compare);

根据qsort manual , 作为比较器函数给出的参数应该是 int (*compar)(const void *, const void *) ,这就是你转换到 (compfn) 后所给予的.至于qsort知道函数接受两个 const void *参数,其表示可能与 person_t * 不同争论。这肯定会导致段错误。不要对 compare 的类型撒谎.将其更改为看起来更像:

int compare(const void *x, const void *y) {
    const person_s *a = x, *b = y;
    /* ... */
}

...而且您不需要强制转换 typedef。

接下来,介绍该函数的返回值。我使用过一些实现,在这些实现中,不合逻辑的返回值会导致段错误。例如,如果 a <= bb <= c , 然后 a <= c ,但您的代码不能保证这一点。事实上,使用您的代码有可能 a <= b , b <= ca > c .我建议确保您的代码保证返回值和词法顺序之间的对应关系。您可以通过返回 1 表示大于,0 表示等于或 -1 表示小于。

#define lexical_order(x,y) ((x > y) - (x < y))
int compare(const void *x, const void *b){
  const person_s *a = x, *b = y;
  return a->birthday.year != b->birthday.year   ? lexical_order(a->birthday.year,  b->birthday.year)
       : a->birthday.month != b->birthday.month ? lexical_order(a->birthday.month, b->birthday.month)
                                                : lexical_order(a->birthday.day,   b->birthday.day);
}

我相信您知道您应该检查 realloc 的返回值... 例如:

void *temp = realloc(persons.arr, persons.cap * sizeof(persons.arr[0]));
if (temp == NULL) {           /* If we don't check return value prior *
                               * to assigning to persons.arr, we      *
                               * might leak some memory...            */
    puts("Error in realloc");
    free(persons.arr);
    exit(-1);
}
persons.arr = temp;

最后,也是最重要的(这可能是你的错误),你确定吗?

int nitems = persons.cap*sizeof(persons.arr[0]);

如果您打算将此作为项目数传递给 qsort (这是通常的),那么我认为应该是:

size_t nitems = persons.n;

附言万一你第二次错过了它,你可能应该审核你的代码以确保你正在使用 size_t仅存储数组索引。

附言别忘了 free(persons);在你的程序结束时,所以当你使用 valgrind 时,你不会得到内存泄漏的报告。 ...

P.P.P.S. valgrind太棒了!

关于c - qsort 段错误结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30418671/

相关文章:

c - 释放链表中的节点

C 函数参数,内存对齐注意事项

c - 对于像“请勿打扰”这样的应用程序来说,处理一天中的时间的理想数据结构应该是什么?

c - 从 C 函数返回数组

javascript - javascript 上的数组减少返回错误值并具有数组可链接性

c - 类型结构的不完整定义

C系统函数返回sh : Invoke-Item command not found

c - Xilinx MicroBlaze 浮点兼容性

Javascript数组播放声音

arrays - 有没有办法在不使用循环的情况下将结构转换为数组?