簡體   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