3

C で学生の構造体をソートしようとしています。qsort を使用して単純な文字列比較を行っています。なぜセグフォルトが発生するのかわかりません。コンパレータ関数で構造体を適切にキャストおよび逆参照しています。私はしばらくこれに頭を悩ませてきました。

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

typedef struct Student {
    char * last;
    char * first;
    char * social;
    int age;
    float gpa;
    enum { ComputerScience = 1, History, Biology } major;
} Student;

void gpa_comp(Student **);
int gpa_comparator(const void * a, const void * b);
void name_comp(Student **);
int name_comparator(const void * a, const void * b);
void make_student_list(Student **);
int student_cmp(const void * a, const void * b);
void print_students (Student ** s, size_t len);
int flt_cmp(const float a, const float b);

int main(int argc, char const *argv[])
{
    int i;
    struct Student ** students = (struct Student **)malloc(5 * sizeof(struct Student *));

    for (i = 0; i < 5; ++i) {
        students[i] = (struct Student *)malloc(sizeof(struct Student));
    }

    make_student_list(students);

    printf("Students in no order\n");
    print_students(students, 5);

    printf("\n");
    printf("Students Sorted By First Name Asc\n");
    name_comp(students);

    return 0;
}

int gpa_comparator(const void * a, const void * b){
    const Student * s1 = (const Student *)a;
    const Student * s2 = (const Student *)b;
    return (int)(100.f*s1->gpa - 100.f*s2->gpa);
}

int name_comparator(const void * a, const void * b){
    const Student * s1 = (const Student *) a;
    const Student * s2 = (const Student *) b;
    return strcmp(s1->first, s2->first);
}

void print_students (Student ** s, size_t len) {
    int c;
    for (c = 0; c < len; c++){
        printf("%s - %s - %2f\n", s[c]->first, s[c]->last, s[c] -> gpa);
    }
}

void gpa_comp(Student ** students) {
    size_t len = 5;
    qsort(students, len, len, gpa_comparator);
    print_students(students, len);
}

void name_comp(Student ** students){
    qsort(students, 5, sizeof(Student), name_comparator);
    print_students(students, 5);
}

void make_student_list(Student ** s){
    s[0]->first = "Dave";
    s[0]->last = "Johnson";
    s[0]->social = "362-89-3284";
    s[0]->major = ComputerScience;
    s[0]->gpa = 3.5;

    s[1]->first = "Sally";
    s[1]->last = "Susie";
    s[1]->social = "251-43-9220";
    s[1]->major = History;
    s[1]->gpa = 3.4;

    s[2]->first = "Molly";
    s[2]->last = "Thomas";
    s[2]->social = "123-45-2343";
    s[2]->major = Biology;
    s[2]->gpa = 3.3;

    s[3]->first = "Brett";
    s[3]->last = "Bigler";
    s[3]->social = "523-364-3462";
    s[3]->major = ComputerScience;
    s[3]->gpa = 3.9;

    s[4]->first = "Sandra";
    s[4]->last = "Salami";
    s[4]->social = "724-457-2455";
    s[4]->major = Biology;
    s[4]->gpa = 4.0;
}
4

1 に答える 1

9

Student*の配列ではなく、の配列をソートしていますStudent。したがって、 の呼び出しはの代わりにパラメータをqsort渡す必要があり、コンパレータ関数はパラメータをに変換し、それらを 2 回逆参照する必要があります。sizeof(Student*)sizesizeof(Student)const void *Student **

より良い解決策は、おそらく配列をStudent*の代わりに変更することですStudent**。そうすれば、malloc個々のStudentインスタンスごとに変更する必要がなくなり、変更する必要のあるコードが少なくなります。

于 2012-11-05T19:49:29.407 に答える