#c #pointers
#c #указатели
Вопрос:
У меня возникли некоторые проблемы с функцией, которую мы должны писать. Предположительно, именно так это и должно работать, но это выдает мне ошибку несовместимого типа указателя, и я не уверен, как это исправить.
Проблема заключается в qsort, ссылающемся на функцию compare_last.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_PERSONS 100
//person structure definition goes here
typedef struct{
char last[32];
char first[32];
int year;
}Person;
//function declarations go here
int compare_last(Person * ptr1, Person * ptr2);
void main(void){//main function goes here
char *infilename[20];
char *outfilename[20];
FILE * fptrin;
FILE * fptrout;
int i, j;
Person musicians[MAX_PERSONS];
printf("Enter input file name: ");
scanf("%s", infilename);
printf("Enter output file name: ");
scanf("%s", outfilename);
strcat(*outfilename, ".htm");
fptrin = fopen(*infilename, "r");
fptrout = fopen(*outfilename, "w");
for(i = 0; i < MAX_PERSONS; i )
{
fscanf(fptrin, "%s %s %i", musicians[i].last, musicians[i].first, amp;musicians[i].year);
}
qsort(musicians, i, sizeof(musicians[0]), compare_last);
fprintf(fptrout, "<html>n<body>n<title>LAB14</title>n");
for(j = 0; j < i; j )
{
fprintf(fptrout, "%s %s %i <br>", musicians[j].last, musicians[j].first, musicians[j].year);
}
fprintf(fptrout, "</body>n</html>n");
fclose(fptrin);
fclose(fptrout);
}//end main
//function definitions go here
int compare_last(Person * ptr1, Person * ptr2)
{
int result = strcmp(ptr1 -> last, ptr2 -> last);
if(result != 0)
return resu<
else
return strcmp(ptr1 -> first, ptr2 -> first);
}
Комментарии:
1. Вы пишете
we are supposed to be writing
— означает ли это, что это домашнее задание?
Ответ №1:
int compare_last(Person * ptr1, Person * ptr2);
должно быть
int compare_last(void * ptr1, void * ptr2);
Затем вам нужно выполнить приведение внутри compare_last
Комментарии:
1. Хорошо, итак, как мне привести указатели? Все, что я пытаюсь, не работает, и я не могу найти никаких решений.
2.
Person * personPtr1 = (Person *) ptr1;
3. Он по-прежнему выдает мне несовместимый тип указателя error….am Я неправильно использую qsort? Я изменил код на int compare_last(void * ptr1, void * ptr2) { Person * personPtr1 = (Person *) ptr1; Person * personPtr2 = (Person *) ptr2; int result = strcmp(personPtr1 -> последний, personPtr2 -> последний); если (результат!= 0) возвращает результат; в противном случае возвращает strcmp (personPtr1 -> первый, personPtr2 — > первый); }
4. @Sam: убедитесь, что вы также изменили прототип для
compare_last()
.5. На самом деле параметры функции обратного вызова оба должны быть
const void *
.
Ответ №2:
Прототипом для qsort()
является:
void qsort(void *base, size_t nmemb, size_t size,
int(*compar)(const void *, const void *));
Таким образом, ваша функция сортировки должна либо соответствовать int(*compar)(const void *, const void *)
, либо вам нужно выполнить приведение при вызове qsort().
Если вы хотите выполнить сортировку Person*
, самый простой способ — объявить вашу функцию сортировки как требуется, а затем выполнить приведение внутри функции:
static int compare_last(const void *ptr1, const void *ptr2)
{
const Person *p1 = ptr1, *p2 = ptr2;
int result = strcmp(p1 -> last, p2 -> last);
...
}
тогда вообще нет необходимости приводить, поскольку const void *
отлично преобразуется в const Person *
.
Комментарии:
1. Приведение здесь несоответствующего указателя на функцию вызовет неопределенное поведение, поскольку
qsort
вызовет его с неправильными типами аргументов (const void *
вместоPerson *
).2. @R.: Хорошо, приятно знать. Я ожидаю, что большинство компиляторов сгенерируют там что-то разумное, поскольку const void * и Person *, скорее всего, будут представлены одинаково, но неопределенности, конечно, стоит избегать.
3. Да, на практике (и в POSIX) все указатели имеют одинаковое представление, но лучше не полагаться на это, если вам это действительно не нужно, и есть альтернативный способ написания кода, который понятен и соответствует 100%.