Написание функции сравнения для qsort

Я пишу функцию сравнения, которая сравнивает и упорядочивает имена по возрастанию фамилии и, если обе фамилии одинаковы, по убыванию имен. Функция, которая у меня сейчас есть, этого не сделает.

Вот функция:

int namecmp(const void *p, const void *q)
{
    const name *pp = p;
    const name *qq = q;
    int n;

    if((n = strcmp(pp->last, qq->last)) != 0)
        return n;

    return qq->first - pp->first;
}

Я пытаюсь организовать динамический массив структур, вот мои структуры.

typedef struct
{
char last[NAMESIZE];
char first[NAMESIZE];
}name;

typedef struct
{
int id;
name name;
float score;
}record;

typedef struct {
record *data; /* the dynamic array */
size_t nalloc; /* number of records allocated */
size_t nused; /* number of records in use */
} record_list;

и вот как называется qsort.

qsort(list->data, list->nused, sizeof(list->data[0]), namecmp);

Любая помощь будет оценена по достоинству.

РЕДАКТИРОВАТЬ: я сделал то, что вы предложили, теперь у меня неправильный вывод.

мой вывод:

3456789 Burns, Monty: 100.00
4567890 Simpson, Lisa: 95.00
1234567 Simpson, Homer: 35.50
6666666 Simpson, Bart: 45.00
2345678 Flanders, Ned: 99.50

РЕДАКТИРОВАТЬ 2:

Как я храню строку в структуре.

            if(sscanf(line,"%s", lastname) == 1)
        {

            if(strlen(lastname) < NAMESIZE)
            {
                lastname[0] = toupper((int)lastname[0]);
                strcpy(rec->name.last, lastname);
                break;
            }
        }

person user798774    schedule 31.07.2011    source источник
comment
почему вы думаете, что вам нужен strcmp для фамилии, но не для имени?   -  person AShelly    schedule 31.07.2011


Ответы (2)


Вам также нужно вызвать strcmp по имени, иначе это не сработает (поскольку это просто вычитание адресов в памяти). Измените последнюю строку на

return strcmp(pp->first, qq->first);
person Jesus Ramos    schedule 31.07.2011
comment
Спасибо за быстрый ответ, но теперь функция выводит несколько в неправильном порядке - person user798774; 31.07.2011
comment
Вероятно, это должно быть pp перед qq, если вы не хотите, чтобы имена сортировались в другом порядке, чем фамилии. - person Chris Lutz; 31.07.2011
comment
Я бы рекомендовал использовать strcasecmp(), чтобы справиться с различиями в регистре. - person Gilbert; 31.07.2011
comment
Первый способ должен был быть правильным, отредактированным до исходного, также имел бы значение случай в этом сценарии? - person Jesus Ramos; 31.07.2011
comment
На самом деле я думаю, что это из-за случая. потому что в моей программе я использую toupper для первой буквы после ее проверки. - person user798774; 31.07.2011
comment
Хорошо, если первая буква всегда в верхнем регистре, тогда сравнение в порядке, вместо этого попробуйте strcasecmp() и посмотрите, даст ли это вам то, что вы хотите. - person Jesus Ramos; 01.08.2011
comment
все еще дает мне то же самое - person user798774; 01.08.2011
comment
Это может быть неуместно, но правильно ли вы завершаете свои строки нулем? - person Jesus Ramos; 01.08.2011
comment
Я отредактировал свой исходный пост, чтобы показать, как я сохраняю имя в структуре. - person user798774; 01.08.2011
comment
Я понятия не имею, почему это не будет работать правильно на основе этой функции сравнения, поскольку я только что написал программу-заглушку, которая правильно их сортирует. - person Jesus Ramos; 01.08.2011
comment
Я вставил свой исходный код сюда pastebin.com/xJ7wfRN1 Должно быть, так я сохранил строки - person user798774; 01.08.2011
comment
Я предлагаю вам сделать 1 функцию сравнения для использования в qsort и принять структуру, содержащую имя, оценку и идентификатор. Наличие двух отдельных функций сортировки затрудняет определение того, что происходит. - person Jesus Ramos; 01.08.2011
comment
но имя хранится в другой структуре, значит ли это, что я должен преобразовать имя в имя * имя? - person user798774; 01.08.2011
comment
Меня немного смущает ваш код, вы используете свою собственную реализацию списка или используете массив с realloc? Также вы можете просто проверить запись-›name.first и запись-›name.last и отправить их в strcmp. - person Jesus Ramos; 01.08.2011
comment
Я использую массив с realloc - person user798774; 02.08.2011
comment
Хорошо, тогда попробуйте то, что я рекомендовал ранее, и просто напишите функцию сравнения для структуры, которую вы хотите отсортировать таким образом, чтобы исключить любые несоответствия. - person Jesus Ramos; 02.08.2011

Функция сравнения имеет два сравнения (одно отредактированное), но в другом порядке. Первый имеет strcmp(p, q), а оператор возврата имеет strcmp(q,p). Сделайте их одинаковыми, и это сработает !!

Шаш

person Shash316    schedule 31.07.2011