質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

2回答

276閲覧

C言語 構造体のソート

Minochan

総合スコア14

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2018/07/27 06:02

C言語の構造体のソートについての質問です。

下記のtxtデータを構造体に入れてランキングを出すコードが上手く出力されません。
txtデータの詳細は、1列目が参加者ID,2-5列目がそれぞれ,勝ち,負け,引き分けの数と前回の順位になっていて、それぞれ空白区切りになっています。

txt

1A 28 42 30 6 2B 40 60 0 7 3C 45 45 10 1 4D 36 54 10 4 5E 63 27 10 3 6F 36 54 10 5 7G 56 24 20 2

ソートの仕方は以下の基準に基づいてソートをします。
基準 1:勝率が高い順.勝率は,勝ち数/(勝ち数 + 負け数) で算出し,小数点以下第 4 位を四捨五入するもの
基準 2:基準 1 で勝率が同じ場合,勝ち数が多い順.
基準 3:基準 1 で勝率が同じで,基準 2 で勝数も同じ場合,前回の順位が良い順.

下記のソースコードの出力だとこうなります。

bash

1E G C B F D A

正しい出力は以下のとおりです。

bash

1E G C B D F A

わかるかた、よろしくおねがいします。

C

1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4#define N 256 5typedef struct { 6 char* name; 7 int val[4]; 8 float winrate; 9} item; 10 11void print(item items[50], int id){ 12 for(int i = 0; i < id; i++) { 13 printf("%s ", items[i].name); 14 } 15 printf("\n"); 16} 17 18void Swap(item* item1, item* item2) { 19 item tmp; 20 tmp = *item1; 21 *item1 = *item2; 22 *item2 = tmp; 23} 24 25void sort(item items[50], int id) { 26 for(int i = 0; i < id; i++) { 27 for(int j = i + 1; j < id; j++) { 28 if(items[i].winrate < items[j].winrate) { 29 Swap(&items[i], &items[j]);//基準1 30 //printf("kijyun1\n"); 31 }else if(items[i].winrate == items[j].winrate){ 32 if(items[i].val[0] < items[j].val[0]){ 33 Swap(&items[i], &items[j]);//基準2 34 //printf("kijyun2\n"); 35 }else if(items[i].val[0] == items[j].val[0]){ 36 if(items[i].val[3] < items[j].val[3]){ 37 Swap(&items[i], &items[j]);//基準3 38 //printf("kijyun3\n"); 39 } 40 } 41 } 42 } 43 } 44} 45 46 47int main(int argc,char *argv[]){ 48 FILE *fp; 49 item items[50]; 50 char fname=argv; 51 char line[N]; 52 int i,id = 0; 53 54 fp = fopen(argv[1], "r"); // ファイルを開く。失敗するとNULLを返す。 55 if(fp == NULL) { 56 printf("file not open!\n"); 57 return -1; 58 } 59 while(fgets(line, N, fp) != NULL) { 60 items[id].name = (char*)malloc(sizeof(char) * 10); 61 sscanf(line, "%s %d %d %d %d", items[id].name, &items[id].val[0], &items[id].val[1], &items[id].val[2], &items[id].val[3]); 62 items[id].winrate = 0; 63 items[id].winrate = (float) items[id].val[0]/(items[id].val[0]+items[id].val[1]); 64 //printf("%s:",items[id].name); 65 //printf("%f\n",items[id].winrate); 66 id++; 67 } 68 fclose(fp); // ファイルを閉じる 69 sort(items, id); 70 print(items, id); 71 return 0; 72}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

まずアタリをつけるために
プログラムが出した順位と正しい順位を見比べると
基準3の前回の順位が良い順という部分で間違えている事が分かります

んで、それを基に判定部分を見ると

if(items[i].val[3] < items[j].val[3]){

上位が下位よりも前回の順位が小さければ交換しています。

順位は普通小さい方が良いので、ここの判定が逆だと分かります。

投稿2018/07/27 06:13

asm

総合スコア15147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Minochan

2018/07/27 06:55

回答ありがとうございます 単純なミスでしたね。ご指摘感謝します。
guest

0

原因としては既にasmさんが回答されているとおりです。


このような比較関数を用意しておくと、ロジックがわりあいシンプルになりますよ。

C

1int item_compare(item const *arg1, item const *arg2) { 2 if(arg1->winrate < arg2->winrate) return 1; 3 if(arg1->winrate > arg2->winrate) return -1; 4 5 if(arg1->val[0] < arg2->val[0]) return 1; 6 if(arg1->val[0] > arg2->val[0]) return -1; 7 8 if(arg1->val[3] > arg2->val[3]) return 1; 9 if(arg1->val[3] < arg2->val[3]) return -1; 10 11 return 0; 12}

C

1void sort(item items[], int id) { 2 for(int i = 0; i < id; i++) { 3 for(int j = i + 1; j < id; j++) { 4 if(item_compare(&items[i], &items[j]) > 0) { 5 Swap(&items[i], &items[j]); 6 } 7 } 8 } 9}

少し改造するとqsortのコールバック関数としても扱えます。


ついでに。mallocに対するfreeがないことが非常に気になります。
この場合参加者IDの最大長を決め打って、配列で確保した方が楽なのでは。

投稿2018/07/27 06:39

LouiS0616

総合スコア35660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Minochan

2018/07/27 06:56

回答ありがとうございます。 このようにすれば簡略化になるのですね! ご指摘感謝します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問