2017-02-15 122 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