2017-02-15 114 views
1

我正在編寫一個小代碼來測試未完全填充的數組上的qsort。帶有數組結構的Qsort更改結構的內容

但是,每當我運行它,數據完全擦除一些隨機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

比較功能應該返回一個負數,零或正值。你的只返回零或一個。如果它被稱爲「比較(a,b)」並返回一個負數,那麼當它被稱爲「比較(b,a)」時,它必須返回一個正數。這是'qsort()'的所有比較函數的基本要求。另外,你的函數是通過結構指針來比較結構的(當對結構數組進行排序時)。實際上,你將_pointers數組排序爲structures_;你需要一個不同的函數來傳遞一個指向指針的指針。 –

+2

你的比較函數有一些問題......它應該返回一個負/零/正/小於/等於/更大,但因爲'!'只能返回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