2012-05-04 5 views
4

qsort와 비교할 수 있는지 잘 모르겠지만 구조체에 대한 포인터 배열은 내가 비교할 (문자열) 것이 아니기 때문에 qsort와 관련이 있는지 잘 모르겠습니다. 여기 qsort()를 사용하여 문자열을 포함하는 구조체에 대한 포인터 정렬

내 프로그램의 축소 된 버전 (모든 학생 데이터가 우리를 qsort를 (호출하기 전에 핵심에) 및 가정 N 정렬 할 레코드 수입니다)입니다 :

struct student { 
     char lname[NAMESIZE + 1]; 
     char fname[NAMESIZE + 1]; 
     short mid; 
     short final; 
     short hmwks; 
}; 

int cmp(const void *, const void *); 

int 
main(int argc, char **argv) 
{ 
     int n; 
     struct student *data[MAX]; 

     qsort(data, n, sizeof(struct student *), cmp); 

     return 0; 
} 

int 
cmp(const void *p0, const void *p1) 
{ 
     return strcmp((*(struct student *) p0).lname, 
         (*(struct student *) p1).lname); 
} 

답변

3

그것은 뭔가해야한다은 이 같은 : cmp()에 전달 될 것입니다 무엇

int 
cmp(const void *p0, const void *p1) 
{ 
     // pn is a pointer to an element of the array, 
     // so, it's effectively a pointer to a pointer to a struct. 
     // Therefore, we need to cast it appropriately to struct student **. 
     // To get a pointer to a struct from it, we dereference it once, 
     // hence the "*". Then we need to extract a pointer to the beginning 
     // of a string, hence the "->". 
     return strcmp((*(struct student **) p0)->lname, 
         (*(struct student **) p1)->lname); 
} 
+0

감사합니다. – Derek

4

은 (void*의 모습에서) struct student** 매개 변수입니다. 그래서과 같이 cmp()을 변경

int 
cmp(const void *p0, const void *p1) 
{ 
     struct student* ps0 = *(struct student**) p0; 
     struct student* ps1 = *(struct student**) p1; 

     return strcmp(ps0->lname, ps1->lname); 
} 
0

다른 답변을 한 작은 세부하지만, 모든 일에 정확합니다. 난 그냥 이걸 쳤어. 그래서 누군가 다른 사람이 극도로 건방진 컴파일러로 고생하고있는 것을 대비해서 여기에 남겨 두겠다.

qsort() 비교기는 두 개의 const void * 매개 변수를 허용합니다. 즉, 실제 struct에 대한 포인터를 얻기 위해 참조를 취소 할 때는 const -ness를 유지해야합니다. 당신은 C 언어의 모든 단일 규칙을 따르도록했다 경우에 따라서, 당신의 코드는 다음과 같습니다

int 
cmp(const void *p0, const void *p1) 
{ 
    const struct student* ps0 = *(const struct student* const*) p0; 
    const struct student* ps1 = *(const struct student* const*) p1; 

    return strcmp(ps0->lname, ps1->lname); 
} 

주 구성은 "에서 const const를 포인터"- 그건 당신이 컴파일러를 말하고를 그 원래의 포인터 어떤 점에서 (p0p1)은 const- 상태를 잃게됩니다. 먼저이를 const * const *으로 간접 참조 한 다음 const *으로 참조를 취소하십시오. const **을 단순히 사용하는 경우 에서 * (비 -const) 포인터가 사용됩니다.이 포인터는 원래 const-ness가 const void * 인 것을 삭제합니다.

관련 문제