2017-02-15 1 views
1

완전히 채워지지 않은 배열에서 qsort를 테스트하기 위해 작은 코드를 작성하고 있습니다.구조체의 배열을 가진 Qsort가 구조체의 내용을 변경합니다.

하지만 실행할 때마다 데이터가 임의의 정수로 완전히 지워집니다.

나는 왜 this question을 보았고 그 코드는 잘 돌아 갔지만 나는 왜 내 것이되지 않을지 이해하지 못한다. 드미트리에

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

#include <time.h> 

struct proc { 
    long unsigned int user_time; 
    long unsigned int system_time; 
    char *name; 
    int pid; 
}; 


static int compare(const void * a, const void * b) 
{ 
    const struct proc *p1 = a; 
    const struct proc *p2 = b; 

    if ((p1->system_time + p1->user_time) > (p2->user_time + p2->system_time)) 
    return -1; 
    else if ((p1->system_time + p1->user_time) == (p2->user_time + p2->system_time)) 
    return 0; 
    else 
    return 1; 
} 

int main() 
{ 
    int used_size = 0; 
    srand (time(NULL)); 
    struct proc **processes = malloc(sizeof(struct proc*) * 20 + 1); 
    for (int i = 0; i < 20; i++) { 
     processes[i] = malloc(sizeof(struct proc)); 
     processes[i]->user_time = 0; 
     processes[i]->system_time = 0; 
     processes[i]->name = NULL; 
     processes[i]->pid = -1; 
    } 

    for (int i = 0; i < 14; i++) 
    { 
     processes[i]->user_time = rand()%10; 
     processes[i]->system_time = 0; 
     processes[i]->pid = i*2; 
     used_size++; 
    } 

    for (int i = 0; i < used_size;i++) 
    { 
     printf("%d %lu \n",i,processes[i]->user_time); 
    } 

    printf("\n\n\n"); 
    qsort(processes, used_size, sizeof(struct proc *), compare); 

    for (int i = 0; i < used_size;i++) 
    { 
     printf("%d %d \n",i,processes[i]); 
    } 


} 
+2

. 너의 것은 0 또는 1만을 반환한다. 'compare (a, b)'로 호출되어 음수를 반환하면'compare (b, a)'로 호출 할 때 양수를 반환해야합니다. 이것은'qsort()'의 모든 비교 함수의 기본 요구 사항입니다. 또한 함수는 구조체에 대한 포인터를 통해 구조체를 비교하기위한 것입니다 (구조체 배열을 정렬 할 때). 사실 struct_pointers 배열을 정렬하고 있습니다. 포인터에 포인터를 전달해야하는 다른 함수가 필요합니다. –

+2

비교 함수에는 몇 가지 문제가 있습니다 ... 더 작거나 같음/더 큰 값에 대해 음수/0/양수를 반환해야하지만 '!'만 1 또는 0을 반환 할 수 있기 때문에 인수가 포인터가됩니다. 구조체에 대한 포인터 인 비교할 배열의 요소 (설정에서) ... 포인터에 대한 포인터 여야합니다. 구조체를 직접 가리키는 것처럼 취급하지만 포인터에 대한 포인터 여야합니다. – Dmitri

답변

0

감사 :

인수 자체가 (당신의 설정에서)이 구조체에 대한 포인터와 비교되는 배열의 요소에 대한 포인터가 될 ... 그래서 그들은 것 포인터에 대한 포인터 여야합니다. 비록 마치 구조체를 직접 가리키는 것처럼 취급합니다.

문제는 "비교"함수였다 비교 기능은 제로, 음 또는 양의 값을 리턴하도록되어

static int compare(const void * a, const void * b) 
{ 
    const struct proc *p1 = *(struct proc **)a; 
    const struct proc *p2 = *(struct proc **)b; 
    // 0ull to prevent int overflow 
    if ((0ull + p1->system_time + p1->user_time) > (0ull + p2->user_time + p2->system_time)) 
     return -1; 
    else if ((0ull + p1->system_time + p1->user_time) == (0ull + p2->user_time + p2->system_time)) 
     return 0; 
    else 
     return 1; 
} 
+1

세부 정보 : 시스템 및 사용자 시간 추가로 오버플로를 방지하기 위해 다시 쓰기가 필요할 수 있습니다. 'unsigned long long'이 더 넓을 때의 간단한 해결책은'(0ull + p1-> system_time + p1-> user_time)> (0ull + p2-> user_time + p2-> system_time)' – chux

+0

@ chux : 실행 시간이 68 CPU를 넘는 많은 프로그램이 있습니다. –

+0

@JonathanLeffler 큰 걱정거리는 아니지만 우려 할 때 비용이 많이 올 수 있습니다. 분명히 성공적인 코드는 모든 확장 응용 프로그램에 사용됩니다. [6 억 3 천만 유로 실수] (https://en.wikipedia.org/wiki/Ariane_5#Notable_launches)는 코드가 "물리적으로 제한되어 있거나 큰 오차가 있다는"가정 때문에 탐지되지 않은 수학 오버플로가 원인이었습니다. – chux