qsort 创建非特定数量的零

qsort creates a non specific number of zeros

所以我的程序从文件中读取整数,同时跳过以 # 开头的行,然后存储在数组中并使用 qsort 函数排序打印它们。然而,当它们被打印时,由于某种原因,它在开始时打印了一些零,然后是排序后的数字。如果数字对是 60,我得到 21 个零,如果数字对是 103688,它打印 60151 个零。

输入文件:

#Skip
#These
#Lines
25  8
25  19
25  23
25  28
25  29
25  30
25  33
25  35
25  50
25  54
25  55

节目是:

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


typedef struct {
    int start;
    int end;   
} path;

int cmp(const void *a,const void *b){
    int l=((path*)a)->start;
    int r=((path*)b)->start;

    if(l>r)
        return 1;
    if(l<r)
        return -1;
    if(l==r)
        return 0;
}

int doublesize(path** array,int n){
    path* new_array=malloc(n*2*sizeof(path));
    if(new_array==NULL){
        printf("Error allocating memory\n");
        abort();
    }

    for(int i=0;i<n;i++){
        new_array[i]=(*array)[i];
    }
    free(*array);
    *array=new_array;
    n*=2;
    return n;
}

int main()
{
    int maxsize=10;
    int test;
    path* array=malloc(maxsize*sizeof(path));
    if(array==NULL) {
        printf("Error allocating memory\n");
        abort();
    }

    FILE* fd=fopen("Test.txt","r");
    if(fd==NULL) {
        printf("Error opening file\n");
        abort();
    }
    char buff[200];
    int counter=0;

    char c;
    while(fgets(buff,200,fd)) {
        c=buff[0];
        if(c=='#') {
            continue;
        }
        sscanf(buff,"%d%d",&array[counter].start,&array[counter].end);
        counter++;
        if(counter==maxsize){
           maxsize=doublesize(&array,maxsize); 
        }
    }
    counter=0;
    qsort(&array[0],maxsize,sizeof(path),cmp);
    for(int i=0;i<maxsize;i++){
        printf("%d\t%d\n",array[i].start,array[i].end);
        if(array[i].start==0)
            counter++;
    }
    printf("%d\n",counter);
    fclose(fd);
    free(array);
    return 0;
}

您正在排序然后打印 maxsize 个元素,而您的数组仅包含 counter 个元素(在您的第一个 while 循环之后)。排序和打印时应使用准确的元素数。

您看到很多 0 纯属巧合。当您使用 malloc() 分配 space 时,数组的内容是 undefined,这意味着您没有明确覆盖的所有内容都将具有未定义的值(它可以是 0 或者它可以是另一个随机值)。排序时,所有 0 都会移到开头,但任何其他未定义的(而不是 0)实际上都会进入数据的中间,可能与真实数据无法区分.

这不是 qsort 的错,这是 malloc 的错(实际上最终是你的错)。

TL;DR:保留一个变量,其中包含数组中 确切数量 的元素,并且永远不会在该数量之后进行操作。

一个快速的解决方案(我用 ^^^ 标记了修改):

int total = 0;
//  ^^^^^
int counter = 0;
char c;

while(fgets(buff, 200, fd)) {
    if(buff[0] == '#')
        continue;

    sscanf(buff,"%d%d", &array[counter].start, &array[counter].end);
    total++;
//  ^^^^^

    if(total == maxsize)
//     ^^^^^
        maxsize = doublesize(&array, maxsize);
}

qsort(&array[0], total, sizeof(path), cmp);
//               ^^^^^

for(int i = 0; i < total; i++){
//                 ^^^^^
    printf("%d\t%d\n", array[i].start, array[i].end);

    if(array[i].start == 0)
        counter++;
}