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

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

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

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

ソート

複数のデータを、順序性に従って並べ替えること。 データ処理を行う際に頻繁に用いられ、多くのアルゴリズムが存在します。速度、容量、複雑さなどに違いがあり、高速性に特化したものにクイックソートがあります。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

2回答

2165閲覧

C言語で構造体の配列のソートがしたい

gamuq

総合スコア3

C

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

ソート

複数のデータを、順序性に従って並べ替えること。 データ処理を行う際に頻繁に用いられ、多くのアルゴリズムが存在します。速度、容量、複雑さなどに違いがあり、高速性に特化したものにクイックソートがあります。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2020/05/27 17:49

編集2020/05/27 18:06

前提・実現したいこと

プログラムの実行時に学生の種類を type で区別し,適切な構造体を選択し,必要な領域を確保してから,学生の情報を蓄える.学生の種類の入力に応じて,指定された種類の学生の情報を id の昇順で出力する

発生している問題・エラーメッセージ

idの昇順で出力することができません.下のソースコードのままコンパイルすると入れた順に出力されます.ソートしようとqsortなど試しましたがうまくいきません.

該当のソースコード

#include <stdio.h> #include <string.h> #include <stdlib.h> #define BUFSIZE 80 #define STDNT 100 #define ST_UNDERGRADUATE 10 #define ST_POSTGRADUATE 20 struct student { int type; int id; char account[9]; }; struct undergraduate { int type; int id; char account[9]; char program[20]; }; struct postgraduate { int type; int id; char account[9]; char department[20]; char supervisor[20]; }; void set_undergraduate(struct undergraduate *s, int type, int id, char *account, char *program) { int i; s->type = type; s->id = id; for(i=0;i<9;i++) { s->account[i]= account[i]; } for(i=0;i<20;i++) { s->program[i] = program[i]; } } void set_postgraduate(struct postgraduate *s, int type, int id, char *account, char *department, char *supervisor) { int i; s->type = type; s->id = id; for(i=0;i<9;i++) { s->account[i]= account[i]; } for(i=0;i<20;i++) { s->department[i] = department[i]; } for(i=0;i<20;i++) { s->supervisor[i] = supervisor[i]; } } \追加しました int cmp( const void *p, const void *q ) { return ((struct student*)p)->id - ((struct student*)q)->id; } void search(struct student *students[STDNT], int n, int type) { struct student *selected[100]; int i, j, numSameType=0; for(i=0; i<n; i++) { if(students[i]->type == type) { selected[numSameType++] = students[i]; } } \追加しました int m = sizeof selected / sizeof( struct student ); qsort( selected, m, sizeof(struct student), cmp ); for (i=0; i<numSameType; i++) { if (selected[i]->type==ST_UNDERGRADUATE) { printf("%d %d %s %s\n", selected[i]->type, selected[i]->id, selected[i]->account, ((struct undergraduate*)selected[i])->program); } else if (selected[i]->type==ST_POSTGRADUATE) { printf("%d %d %s %s %s\n", selected[i]->type, selected[i]->id, selected[i]->account, ((struct postgraduate*)selected[i])->department, ((struct postgraduate*)selected[i])->supervisor); } } } int main(void) { struct student *students[STDNT]; char buf[BUFSIZE], *account, *param1, *param2; int numStudent, len, type, id; for (numStudent=0; numStudent<STDNT; ) { if (!fgets(buf, sizeof(buf), stdin)) break; if (strlen(buf)==0 || buf[0]=='\n') { break; } len = strlen(buf); if (len<=3) break; if (buf[len - 1] == '\n') buf[len - 1] = '\0'; buf[2] = '\0'; type = atoi(buf); buf[10] = '\0'; id = atoi(buf+3); buf[19] = '\0'; account = buf + 11; while (*account == ' ') account++; param1 = account + 9; while (*param1 == ' ') param1++; if (type==ST_POSTGRADUATE) { param2 = param1; while (*param2 != ' ') param2++; *param2++ = 0; while (*param2 == ' ') param2++; } if (type==ST_UNDERGRADUATE) { students[numStudent] = (struct student*)malloc(sizeof(struct undergraduate)); set_undergraduate((struct undergraduate*)students[numStudent], type, id, account, param1); } else if (type==ST_POSTGRADUATE) { students[numStudent] = (struct student*)malloc(sizeof(struct postgraduate)); set_postgraduate((struct postgraduate*)students[numStudent], type, id, account, param1, param2); } numStudent++; } type = atoi(buf); search(students, numStudent, type); for (--numStudent; numStudent>=0; numStudent--) free(students[numStudent]); return 0; }

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

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

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

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

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

dodox86

2020/05/27 17:56

> 下のソースコードのままコンパイルすると入れた順に出力されます.ソートしようとqsortなど試しましたがうまくいきません. 入れた順に表示しているのですから当然そのように表示されます。ご提示のコードではqsortなどが使われていませんが、標準のqsort関数で構造体でもソートできます。どのように試してダメだったのか、コードで示しましょう。
kazuma-s

2020/05/28 00:14

5行ぐらいでいいので入力データを 追加してください。
guest

回答2

0

ベストアンサー

qsortを使ったコード部分で、2点、間違えています。

(1) qsortの呼び出し時の指定間違い

qsortを実行するときのソート対象の要素数は、numSameTypeの値でよいはずです。また、要素のサイズはstruct student *selected[100]と定義したポインタの配列の各要素のサイズなので、ポインタのサイズを指定しなければなりません。

C

1//元のコード int m = sizeof selected / sizeof( struct student ); 2//元のコード qsort( selected, m, sizeof(struct student), cmp ); 3 4 /* 要素数の計算が間違っている。 struct student *selected[100]と言うポインターの配列の 5 * 要素の内、同じタイプのものに関して対して比較、ソートするので、numSameTypeで良い。 6 * 比較する要素のサイズはポインターのサイズ(sizeof(struct student *)) 7 */ 8 qsort(selected, numSameType, sizeof(selected[0]), cmp);

(2) 比較関数での指定間違い
比較関数のcmpで引数として渡されてくるものは、struct student *selected[100]と言うポインタ配列の各要素へのポインタなので、ポインタへのポインタです。したがって以下のようにしないと構造体の実体にたどり着けません。

C

1int cmp( const void *p, const void *q ) { 2 //return ((struct student*)p)->id - ((struct student*)q)->id; 3 4 /* 引数として渡されてくるものは、struct student *selected[100]と定義した 5 * ポインタ配列の各要素へのポインタなので、ポインタへのポインタとなる。 6 */ 7 struct student *ps1 = *((struct student **)p); 8 struct student *ps2 = *((struct student **)q); 9 int ret = ps1->id - ps2->id; 10 return ret; 11}

上記修正内容を適用して実行した例です。ID部分がソートされていないテスト用のデータを使います。(質問者さんが使っている正規のデータフォーマットが分からなかったので、ID部分以降はダミーです)

sh

1$ cat data.txt 210,0000000,ACCOUNT0#XXXXXXXXXXXXXXXXXXXX 310,0000001,ACCOUNT1#XXXXXXXXXXXXXXXXXXXXX 410,0000002,ACCOUNT2#XXXXXXXXXXXXXXXXXXXXX 510,0000003,ACCOUNT3#XXXXXXXXXXXXXXXXXXXXX 610,0000010,ACCOUN10#XXXXXXXXXXXXXXXXXXXXX 710,0000009,ACCOUNT9#XXXXXXXXXXXXXXXXXXXXX 810,0000008,ACCOUNT8#XXXXXXXXXXXXXXXXXXXXX 910,0000007,ACCOUNT7#XXXXXXXXXXXXXXXXXXXXX

実行例です。要望どおり、ID部分がソートされて出力されるのが分かります。

sh

1$ gcc -Wall t1.c -o t1 2t1.c: In function ‘search’: 3t1.c:82:12: warning: unused variable ‘j’ [-Wunused-variable] 4 int i, j, numSameType=0; 5 ^ 6 7$ ./t1 < data.txt 810 0 ACCOUNT0 XXXXXXXXXXXXXXXXXXXX 910 1 ACCOUNT1 XXXXXXXXXXXXXXXXXXXX 1010 2 ACCOUNT2 XXXXXXXXXXXXXXXXXXXX 1110 3 ACCOUNT3 XXXXXXXXXXXXXXXXXXXX 1210 7 ACCOUNT7 XXXXXXXXXXXXXXXXXXXX 1310 8 ACCOUNT8 XXXXXXXXXXXXXXXXXXXX 1410 9 ACCOUNT9 XXXXXXXXXXXXXXXXXXXX 1510 10 ACCOUN10 XXXXXXXXXXXXXXXXXXXX 16$ 17

投稿2020/05/28 01:15

dodox86

総合スコア9183

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

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

gamuq

2020/05/28 01:33

おっしゃる通りでうまくいったようです.ありがとうございました.
guest

0

qsort( selected, m, sizeof(struct student *), cmp );
にしたらどうなりますか?
ソート対象はポインタのはずです。

投稿2020/05/28 00:24

kazuma-s

総合スコア8224

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

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

gamuq

2020/05/28 01:31

解決致しました.ありがとうございました.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問