2009-11-27 4 views
2

IP 묶음을 정렬하고 있지만 어떤 이유로 그들은 잘못된 순서로 나타납니다. 나는 어디에서 문제가 될 수 있는지 잘 모르겠습니다.구조체 - qsort를 사용하여 C- 문자열 정렬

66.249.71.3  
190.148.164.245 
207.46.232.182 
190.148.164.245 
190.148.164.245 
202.154.114.253 
190.148.164.245 
190.148.164.245 
66.249.71.3  
190.148.164.245 
202.154.114.253 

여기에서 나는 그들을 정렬하는 방법입니다.

typedef struct { 
    char *ip; 
} mystruct; 

/* qsort */ 
int struct_cmp(const void *a, const void *b) 
{ 
    mystruct *ia = (mystruct *)a; 
    mystruct *ib = (mystruct *)b; 
    return strcmp(ia->ip, ib->ip); 
} 
... 
qsort(a_struct, 11, sizeof(mystruct*), struct_cmp); 
for(..){ 
    printf("%s\n",a_struct[i]->ip); 
} 

어떤 도움을 주시면 감사하겠습니다. 감사합니다

+0

입력 또는 출력의 샘플을 제공 했습니까? – FrustratedWithFormsDesigner

+0

출력을위한 샘플 – Josh

답변

7

mystruct에 대한 포인터 배열이 있지만이 비교 함수를 사용하는 qsort에는 mystruct의 간단한 배열이 필요합니다. mystruct*의 배열을 정렬하려면 비교 함수에 간접의 또 다른 레벨을 추가해야합니다

int struct_cmp(const void *a, const void *b) { 
    mystruct *ia = *(mystruct **)a; 
    mystruct *ib = *(mystruct **)b; 
    return strcmp(ia->ip, ib->ip); 
} 
+0

실제로이 일을합니다. 감사! – Josh

+0

Josh, 디버거에서 코드를 실행 시키거나'struct_cmp()'함수 안에서'printf()'에 대한 호출을 추가했다면 포인터가 잘못되었을 때 IP 주소가 쓰레기라는 것을 알았을 것입니다. 따라서, 디버깅을위한 훌륭한 기술 : 상황이 이상하게 작동 할 때, 포인터가 포인터를 가리키고 있는지 확인하십시오. :-) – steveha

+0

Nitpick : 당신은 Constance를 멀리 던지고 있기 때문에, 여기 const-correct되고 있지 않습니다. 이 경우에는 해를 끼치 지 않지만 'mystruct * ia = * (mystruct * const *) a' 등이어야합니다. –

3

당신은 문자열로 IP 주소를 정렬합니다. 정규화 된 경우 실제로 작동합니다. 66.249.71.3 대신에 066.249.071.003이 있어야합니다.

나는 가장 좋은 방법은 점선 IP 주소를 32 비트 정수로 변환하는 함수를 사용하여 결과 정수를 정렬 키로 사용하여 정렬하는 것입니다.

이 변환을 수행하려면 inet_addr()을 사용할 수 있어야합니다. 이를 프로그램에 추가하십시오 :

#include <arpa/inet.h> 

문서 here.

+0

잘못된 문제에 대한 올바른 대답 (sth의 답변 참조) – Grandpa

+0

나는 또한 이것이 좋은 방법이 될 것이라고 생각합니다! 덕분에 – Josh

+0

나는 주요 문제를 놓친 것에 동의한다. 하지만 일단 sth의 대답을 사용하면, 그는이 문제로 인해 이상한 정렬을 보게 될 것이므로, 실제로 두 답변이 가장 좋은 해결책입니다. – steveha

2

정렬 코드를 고정 적어도 두 가지 방법이 있습니다. 하나는 qsort() 호출을 일치시키기 위해 비교 함수를 수정하는 것입니다. 다른 하나는 qsort()에 대한 호출을 비교기와 일치하도록 수정하는 것입니다. 올바른 수정은 배열의 정의에 따라 다르지만 가장 간단한 선언은 구조체 포인터가 아닌 구조체의 배열입니다. 따라서,이 작업 코드 - 원본 비교하지만 다른 호출을 사용하여()를 qsort합니다 :

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

typedef struct { 
    char *ip; 
} mystruct; 

static mystruct a_struct[] = 
{ 
    "66.249.71.3", 
    "190.148.164.245", 
    "207.46.232.182", 
    "190.148.164.245", 
    "190.148.164.245", 
    "202.154.114.253", 
    "190.148.164.245", 
    "190.148.164.245", 
    "66.249.71.3", 
    "190.148.164.245", 
    "202.154.114.253", 
}; 

/* qsort */ 
static int struct_cmp(const void *a, const void *b) 
{ 
    mystruct *ia = (mystruct *)a; 
    mystruct *ib = (mystruct *)b; 
    return strcmp(ia->ip, ib->ip); 
} 

static void print_list(mystruct *list, int n) 
{ 
    int i; 
    for (i = 0; i < n; i++) 
     printf("%2d: %s\n", i, list[i].ip); 
} 

#define DIM(x) (sizeof(x)/sizeof(*(x))) 

int main(void) 
{ 
    print_list(a_struct, DIM(a_struct)); 
    qsort(a_struct, DIM(a_struct), sizeof(mystruct), struct_cmp); 
    print_list(a_struct, DIM(a_struct)); 
} 

을이 그냥 모든 '190.xyz의 주소가 이전에 나타나는와 값의 영숫자 정렬 된 배열을 우리에게 남긴다 다른 것들은 등등. 더 복잡한 비교기가 필요합니다. 하나의 솔루션은 steveha가 대답했습니다.