我正在撰寫一段代碼,讀取一個二進制檔案,分別讀取每個結構域,對輸出進行排序,然后將輸出寫入二進制檔案。
下面是我的代碼。
short int land;
double experience;
short int boys;
int angle;
float industry;
unsigned short thread;
unsigned char shoe。
double kitty;
unsigned long price;
short int father;
char room;
int attraction;
int 蛋糕。
int foot;
char hat[MAX_HAT];
char 巢。
double bean;
};
int compare (const void * a。const void * b)
{
struct test** a1 = (struct test**) a;
struct test** b1 = (struct test**)b;
//experience(asc)
if ((*a1)-> experience > (*b1)-> experience)
{
return 1;
}
if ((*a1)-> experience < (*b1)-> experience)
{
return 1;
}
//land(asc); }
if ((*a1)-> land > (*b1)-> land)
{
return 1;
}
if ((*a1)->land < (*b1)->land)
{
return 1;
}
//nest(desc); }
if ((*a1)-> nest > (*b1)-> nest)
{
return -1;
}
if ((*a1)->nest < (*b1)->nest)
{
return 1;
}
/shoe(asc)/span>
if ((*a1)-> shoe > (*b1)-> shoe)
{
return 1;
}
if ((*a1)-> shoe < (*b1)-> shoe)
{
return 1;
}
//hat(desc); }
if (strncmp((*b1) -> hat, (*a1) -> hat, MAX_HAT) != 0)
{
return strncmp((*b1) -> hat, (*a1) -> hat, MAX_HAT)。
}
//boys(asc)。
if ((*a1)-> boys > (*b1)-> boys)
{
return 1;
}
if ((*a1)->boys < (*b1)->boys)
{
return 1;
}
//cake(desc); }
if ((*a1)-> cake > (*b1)-> cake)
{
return -1;
}
if ((*a1)->cake < (*b1)-> cake)
{
return 1;
}
//price(desc); }
if ((*a1)->price > (*b1)->price)
{
return -1;
}
if ((*a1)->price < (*b1)->price)
{
return 1;
}
//bean(desc)。
if ((*a1)-> bean > (*b1)-> bean)
{
return 1;
}
if ((*a1)->bean < (*b1)-> bean)
{
return 1;
}
//room(desc)。
if ((*a1)-> room > (*b1)-> room)
{
return -1;
}
if ((*a1)->room < (*b1)->room)
{
return 1;
}
//father(desc)
if ((*a1)-> father > (*b1)-> father)
{
return -1;
}
if ((*a1)-> father < (*b1)-> father)
{
return 1;
}
//industry(desc); }
if ((*a1)-> industry > (*b1)-> industry)
{
return -1;
}
if ((*a1)-> industry < (*b1)-> industry)
{
return 1;
}
//foot(desc); }
if ((*a1)-> foot > (*b1)-> foot)
{
return -1;
}
if ((*a1)->foot < (*b1)->foot)
{
return 1;
}
//angle(asc)。
if ((*a1)->angle > (*b1)-> angle)
{
return 1;
}
if ((*a1)->angle < (*b1)->angle)
{
return 1;
}
//kitty(asc); }
if ((*a1)->kitty > (*b1)-> kitty)
{
return 1;
}
if ((*a1)->kitty < (*b1)-> kitty)
{
return 1;
}
//attraction(asc)。
if ((*a1)->吸引力 > (*b1)->吸引力)
{
return 1;
}
if ((*a1)->吸引力 < (*b1)->吸引力)
{
return 1;
}
//thread(desc); }
if ((*a1)-> thread > (*b1)-> thread)
{
return 1;
}
if ((*a1)->thread < (*b1)-> thread)
{
return 1;
}
return 0;
}
int main(int argc, char **argv)
{
int size = 8;
int count = 0;
int i;
struct test *t1;
t1 = (struct test*) malloc (size * sizeof(struct test) ) 。
FILE *fp1;
FILE *fp2;
if (! t1)
{
fprintf(stderr, "無法分配記憶體")。
exit(-2) ;
}
fp1 = fopen(argv[1], "rb"/span>)。
fp2 = fopen(argv[2], "wb") 。
if (argc != 3)
{
fprintf(stderr, "不正確的檔案名")。
exit(1)。
}
if (! fp2)
{
fprintf(stderr, "無法打開檔案%s
", argv[2])。)
exit(-3)。
}
if (! fp1)
{
fprintf(stderr, "無法打開檔案%s
", argv[1])。)
exit(-3)。
}
while (!feof(fp1))
{
if ( count >= size)
{
size = size * 2;
t1 = realloc(t1, sizeof(struct test) * size) 。
}
fread(&t1[count].land, sizeof(t1[count].land), 1, fp1) 。
fread(&t1[count].experience, sizeof(t1[count].experience), 1, fp1);
fread(&t1[count].boys, sizeof(t1[count].boy), 1, fp1);
fread(&t1[count].angle, sizeof(t1[count].angle), 1, fp1)。
fread(&t1[count].Industry, sizeof(t1[count].Industry), 1, fp1);
fread(&t1[count].thread, sizeof(t1[count].thread), 1, fp1);
fread(&t1[count].shoe, sizeof(t1[count].shoe), 1, fp1)。
fread(&t1[count].kitty, sizeof(t1[count].kitty), 1, fp1)。
fread(&t1[count].price, sizeof(t1[count].price), 1, fp1) 。
fread(&t1[count].father, sizeof(t1[count].father), 1, fp1)。
fread(&t1[count].room, sizeof(t1[count].room), 1, fp1)。
fread(&t1[count].attraction, sizeof(t1[count].attraction), 1, fp1)。
fread(&t1[count].cake, sizeof(t1[count].cake), 1, fp1)。
fread(&t1[count].foot, sizeof(t1[count].foot), 1, fp1)。
fread(&t1[count].hat, sizeof(t1[count].hat), 1, fp1) 。
fread(&t1[count].nest, sizeof(t1[count].nest), 1, fp1)。
fread(&t1[count].bean, sizeof(t1[count].bean), 1, fp1)。
count ;
}
struct test** t2 = (struct test**) malloc (size * 8)。
for (i = 0; i < count; i )
{
t2[i] = &t1[i];
}
qsort(t2, count - 1, 8, compare) 。
for (i = 0; i < count 1; i )
{
fwrite(&t2[i]->land, sizeof(t2[i]->land), 1, fp2) 。
fwrite(&t2[i]->經驗, sizeof(t2[i]->經驗), 1, fp2) 。
fwrite(&t2[i]->boys, sizeof(t2[i]->boys), 1, fp2);
fwrite(&t2[i]->angle, sizeof(t2[i]->angle), 1, fp2);
fwrite(&t2[i]->行業, sizeof(t2[i]->行業), 1, fp2) 。
fwrite(&t2[i]->thread, sizeof(t2[i]->thread), 1, fp2);
fwrite(&t2[i]->鞋, sizeof(t2[i]->鞋), 1, fp2);
fwrite(&t2[i]->kitty, sizeof(t2[i]->kitty), 1, fp2);
fwrite(&t2[i]->price, sizeof(t2[i]->price), 1, fp2) 。
fwrite(&t2[i]->father, sizeof(t2[i]->father), 1, fp2);
fwrite(&t2[i]->room, sizeof(t2[i]->room), 1, fp2);
fwrite(&t2[i]->吸引力, sizeof(t2[i]->吸引力), 1, fp2);
fwrite(&t2[i]->cake, sizeof(t2[i]->cake), 1, fp2);
fwrite(&t2[i]->foot, sizeof(t2[i]->foot), 1, fp2);
fwrite(&t2[i]->hat, sizeof(t2[i]->hat), 1, fp2) 。
fwrite(&t2[i]->nest, sizeof(t2[i]->nest), 1, fp2);
fwrite(&t2[i]->bean, sizeof(t2[i]->bean), 1, fp2)。
//列印出輸出結果。
printf("%d, %f, %i, %i, %f, %d, %d, %f, %li, %d, %d, %x, %s, %c, %f
", t2[i]->土地, t2[i]->經驗, t2[i]->男孩, t2[i]->角度, t2[i]->工業, t2[i]->螺紋, t2[i]->鞋子, t2[i]-> kitty, t2[i]->price, t2[i]->father, t2[i]->room, t2[i]->attraction, t2[i]->cake, t2[i]->foot, t2[i]->hat, t2[i]->nest, t2[i]->bean)。)
}
fclose(fp1);
fclose(fp2);
free(t1)。
free(t2)。
return 0;
正如你在我的代碼開頭所見,我的int比較函式非常長。如果可能的話,我想讓它變得更簡單(或更短)。排列順序有以下條件。
排序order (按優先級排序)。
經驗按升序排列。
按升序排列的土地。
巢穴以降序排列。
鞋子按升序排列。
帽子按降序排列。
男孩依次遞增。
蛋糕按降序排列。
價格從低到高的順序。
豆子從大到小的順序。
房間按降序排列。
父親按降序排列。
行業按降序排列。
腳的降序排列。
角度從大到小排列。
kitty按升序排列。
吸引力依次遞增。
以降序排列的線。
請您幫助我解決如何做到這一點。 謝謝。
uj5u.com熱心網友回復:
正如你在我的代碼開頭所見,我的int比較函式太長了。如果可能的話,我想讓它變得更簡單。
這聽起來好像你認為短代碼比長代碼更簡單。這并不正確。通常情況下,它實際上是相反的。短代碼通常需要復雜的解決方案,而撰寫易于閱讀和理解的代碼則會導致更多的代碼行。
不要使用復雜的、難以閱讀/理解的解決方案來減少代碼行的數量。保持簡單--即使它需要額外的打字。
使用或多或少復雜的宏解決方案是一個壞主意。使用簡單的C語言,使您的代碼易于理解。
這里是減少代碼行數的一種方法,同時仍然保持簡單C代碼中的內容。
基于函式的解決方案
int compare_int(long long int a, long long int b) { if (a > b) return 1; if (a < b) return -1; return 0; } int compare_unsigned(long long unsigned a。long long unsigned b) { if (a > b) return 1; if (a < b) return -1; return 0; } int compare_double(double a, double unsigned b) { if (a > b) return 1; if (a < b) return -1; return 0;現在你可以對欄位使用這些函式,例如:
struct test** a1 = (struct test**) a; struct test** b1 = (struct test**)b; struct test* pa = *a1。 struct test* p= *b1; int cmp; if ((cmp = compare_int(pa-> land, pb-> land))) return cmp; if ((cmp = compare_double(pa-> experience, pb-> experience)) return cmp; if ((cmp = compare_int(pa->boys, pb->boys)) return cmp; if ((cmp = compare_int(pa->angle, pb->angle)) return cmp; if ((cmp = compare_int(pa->Industry, pb->Industry)) return cmp; ... return 0。注意到
。compare_xxx函式引數是如何用最大的型別來寫的。通過這樣做,它們可以安全地用于所有 "較小 "的型別。然而這可能會有一點性能上的損失。同樣,對于函式的呼叫,但在這里你可以嘗試使用inlineBTW:
char hat[MAX_HAT]。不能使用
>(等)進行比較。你可能想使用strcmp。基于Macro的解決方案
如果你真的想使用一個宏,那么你可以這樣做:
// Kind of ugly macro but not extremely complex... so perhaps okay #define CMP_NUMBER(a, b) (((a) > (b) ) ? (1) : (((a) < (b)) ? (-1) : (0)) int cmp; if ((cmp = CMP_NUMBER(pa->land, pb->land)) return cmp; if ((cmp = CMP_NUMBER(pa-> experience, pb-> experience))) return cmp; if ((cmp = CMP_NUMBER(pa->boys, pb->boys))) return cmp; if ((cmp = CMP_NUMBER(pa->angle, pb->angle)) return cmp; if ((cmp = CMP_NUMBER(pa->Industry, pb->Industry))) return cmp; ... return 0;我更喜歡基于函式的解決方案,但這種宏的解決方案也很好,因為它很簡單。
uj5u.com熱心網友回復:
作為一個初步的改進,你可以替換每一個比較,比如:
if ((*a1)-> experience > (*b1)-> experience) { return 1; } else if ((*a1)-> experience < (*b1)-> experience) { return 1; }與
res = (*a1)->experience > (*a2)-> experience; if (res) return res。 res = (*a1)->經驗 < (*a2)->經驗。 if (res) return -res;
但是這仍然需要你為你的每個
結構欄位撰寫手動比較。這很麻煩,而且在C語言中也沒有 "簡單 "的解決方案--我們最好的解決方案是X-macros。讓我們簡化一下,假定我們有:
struct A { char a; int b; };那么你可以寫這樣的代碼:
然后定義我們的
結構如下:typedef struct { #define X(type, name) type name; X_FIELDS #undef X } A;最后,我們的 "自動 "比較功能:
int compare (const void * a。const void * b) { A* a1 = a; A* b1 = b。 int res; #define X(type, name) res = a1->name > b1->name。 if (res) return res; res = a1->name < b1->name。 if (res) return -res; name; X_FIELDS #undef X }這是相當復雜的,但隨著新的欄位被添加到
結構中,可以很好地擴展。注意,你的
結構變數必須以你希望進行比較的相同順序來宣告。獎勵提示:撰寫X-macros(和一般的宏)可能會變得很棘手,你可以運行
gcc -E來看看你的宏是否以你期望的方式得到處理。uj5u.com熱心網友回復:
在尋求簡單性之前,先檢查正確性
我發現了一個有趣的請求,尋求輕微的性能改進,但卻不能保證代碼的功能無誤:見下文。
無論如何,我們還是要討論一下 OP 的問題。
如何使排序函式更簡單(或更短)
與其說是比較偉大,不如說是先比較不平等
。//if ((*a1)-> experience > (*b1)-> experience) { // return 1; //} //if ((*a1)-> experience < (*b1)-> experience) { // return -1; //} if ((*a1)->experience != (*b1)-> experience) { return ((*a1)->experience > (*b1)-> experience) ? 1 : 1; }沒有太大的不同。
一個微妙的問題是關于不是一個數字的浮點數。 為了避免未定義的行為與
。qsort(),如果compare(a,b)回傳0,compare(b,a)也必須回傳0。如果compare(a,b)回傳一個正數,compare(b,a)必須回傳一個負數。 典型的FP比較函式沒有這些屬性與NANs.//合適的FP比較要在OP的compare()中呼叫。 //副作用,所有的NAN都比其他的 "大"。。 int dbl_cmp(double a, double b) { if (isnan(a)) { if (isan(b)) return 0; //將所有NAN視為同一個 "值"。 return 1; } if (isnan(b)) { return 1; } return (a > b) - (a- b); }代替
!eof(fp1),檢查fread()/code>的回傳值。測驗
malloc()的回傳值。轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/310844.html
標籤:
