繁体   English   中英

C: qsort 在对结构的 unsigned long long 成员进行排序时出现问题

[英]C: qsort has a problem sorting unsigned long long members of a structure

当它们是结构的一部分时,C 的 Qsort 算法不会对 unsigned long long int 进行排序,这应该无关紧要。 这是代码:

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

typedef struct TextData {
  char catalog,  // The catalog code.
       txt[137]; // The text for this object.
  short mv;      // mv * 100.
  unsigned long long indx; // Hash of 2D position.
} txtD;          // 152 bytes.

// The comparison function required by qsort for txtD items.
int cmpTdata(const void *a,
             const void *b) {
  txtD *dataA = (txtD*) a;
  txtD *dataB = (txtD*) b;
  if ((dataB->indx - dataA->indx) < 0) { return 1; }
  else if ((dataB->indx - dataA->indx) > 0) { return -1; }
  else { return 0; }
}

int main(int argc, char** argv) {
  FILE *UNSORTED = fopen("/top/middle/directory/filename", "r");
  if (UNSORTED == NULL) {
    printf("Filename not opened for reading!\n");
    exit(0);
  }

  int stat = fseek(UNSORTED, 0L, SEEK_END);
  if (stat != 0) {
     printf("Fseek on failed to find the end! because %s.\n", strerror(errno));
     exit(0);
  }

  unsigned long long size = ftell(UNSORTED);
  if ((size == 0) && (errno != 0)) {
     printf("Error %d) Ftell is 0! because %s.\n",
            errno, strerror(errno));
     exit(0);
  }

  fclose(UNSORTED);

  int nrItems = size / sizeof(txtD);

  txtD *data = (txtD*) malloc(nrItems * sizeof(txtD));
  if (data == NULL) {
    printf("txtD structure not allocated because:\n%s.\n",
           strerror(errno));
    exit(0);
  }

  // Sort it in order of increasing indx.
  qsort(data, nrItems, sizeof(txtD), cmpTdata);

  // Save the sorted items using fopen and fwrite. I'll spare you the details.
}

这是一个简单读取结构并记录错误的程序的输出:

Item 2) previous index 466715 greater than t.indx 449261!
Item 4) previous index 464265 greater than t.indx 404184!
Item 5) previous index 404184 greater than t.indx 353788!
Item 7) previous index 446334 greater than t.indx 361489!
Item 8) previous index 361489 greater than t.indx 328323!
Item 10) previous index 487465 greater than t.indx 343185!
Item 12) previous index 494247 greater than t.indx 428224!
Item 14) previous index 478868 greater than t.indx 130860!
Item 16) previous index 444180 greater than t.indx 339954!
Item 18) previous index 342195 greater than t.indx 281552!
Item 20) previous index 394250 greater than t.indx 370791!
Item 22) previous index 458202 greater than t.indx 311406!
Item 23) previous index 311406 greater than t.indx 280793!
Item 25) previous index 466171 greater than t.indx 424598!
Item 27) previous index 467144 greater than t.indx 431265!
Item 29) previous index 472449 greater than t.indx 198109!
Item 31) previous index 469376 greater than t.indx 451215!
Item 33) previous index 453004 greater than t.indx 427448!
Item 34) previous index 427448 greater than t.indx 374260!
Item 37) previous index 447735 greater than t.indx 336330!

检查了41个项目,有21个错误。

顺便说一句,因为我不使用 stderr 或其他风格违规而责骂我没有帮助。 为什么 qsort 不排序是。 另请注意,当我对双精度进行排序时,函数 cmpTdata 对其他结构也能正常工作。

蒂亚!

当我对双打进行排序时,函数 cmpTdata 适用于其他结构。

double精度数学不同于无符号数学。 以下永远不会正确,因为无符号永远不会小于 0。

if ((dataB->indx - dataA->indx) < 0) { return 1; }

这意味着代码不是使用会发出警告的良好编译器编译的。 所以最大的遗憾不是“做错数学”,而是没有使用手头的工具。 最好启用所有警告。

foo.c:9:35: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits]

推荐 C 比较习惯用法 - 被各种编译器识别以发出高效代码。

int cmpTdata(const void *a, const void *b) {
  const txtD *dataA = (txtD*) a;
  const txtD *dataB = (txtD*) b;
  return (dataA->indx > dataB->indx) - (dataA->indx < dataB->indx);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM