2017-02-15 16 views
1

Я пишу небольшой код для проверки qsort на массив, который не полностью заполнен.Qsort с массивом struct изменяет содержимое структуры

Но всякий раз, когда я запускаю его, данные полностью удаляются для некоторого случайного int.

Я не понимаю, почему, я посмотрел на 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

Функция сравнения должна возвращать отрицательное, нулевое или положительное значение. Ваш только возвращает ноль или один. Если он вызывается как «compare (a, b)» и возвращает отрицательное число, он должен возвращать положительное число при вызове «compare (b, a)» - ваш нет. Это базовое требование для всех функций сравнения для 'qsort()'. Кроме того, ваша функция предназначена для сравнения структур с помощью указателей на структуры (при сортировке массива структур). Вы фактически сортируете массив _pointers для структур; вам нужна другая функция, которая ожидает передачи указателя на указатель. –

+2

У вашей функции сравнения есть некоторые проблемы ... она должна возвращать отрицательный/нулевой/положительный для less/equal/greater, но из-за '!' Может только возвращать 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 процессорных лет времени выполнения. –

+0

@JonathanLeffler Правда, это не большая проблема, но когда это вызывает беспокойство, это может быть дорогостоящим. По-видимому, успешный код используется для каждого расширяющегося приложения. Ошибка [630 миллионов евро] (https://en.wikipedia.org/wiki/Ariane_5#Notable_launches) была вызвана необнаруженным переполнением математики, потому что код предполагался «физически ограниченным или что существует большая погрешность». – chux