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++;
}
所以我的程序从文件中读取整数,同时跳过以 #
开头的行,然后存储在数组中并使用 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++;
}