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

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

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

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

ソート

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

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

Q&A

解決済

4回答

5371閲覧

C言語 ソート関数を自作したい

Kassy11

総合スコア26

C

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

ソート

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

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

0グッド

1クリップ

投稿2019/06/14 06:57

現在、C言語を用いて構造体の配列のソーティングプログラムを実装しています。
以下のようにqsortを用いて実装していたものを、挟み込み法でソートする自作関数に作り変えたいと思っています。
qsortで使用した比較関数はそのまま使用するつもりです。

main

1if(strcmp(argv[1],"credit")==0){/*argv[1]で指定されたメンバでソートする*/ 2 qsort(grade_data,n,sizeof(SRec),comp_credit); 3 }else if(strcmp(argv[1],"gpa")==0){ 4 qsort(grade_data,n,sizeof(SRec),comp_gpa); 5 }else if(strcmp(argv[1],"name")==0){ 6 qsort(grade_data,n,sizeof(SRec),comp_name); 7 }else{ 8 printf("ソートしたいフィールドをcredit/gpa/nameの中から正しく選択してください。\n"); 9 }

※grade_dataは構造体の配列のポインタ、nは要素数です。(これ以前のコードでファイル入力関数でを実装しており、その引数として受け取っている)

としていたものを

main

1void gpa_sort(SRec *grade_data,int n, int (*comp_gpa)(const void*,const void*));/*自作ソート関数:ソート対象の構造体へのポインタ、要素数、voidへのポインタを引数に取る比較関数へのポインタ*/ 2void credit_sort(SRec *grade_data,int n, int (*comp_credit)(const void*,const void*)); 3void name_sort(SRec *grade_data,int n,int (*comp_name)(const void*,const void*)); 4 5if(strcmp(argv[1],"credit")==0){/*argv[1]で指定されたメンバでソートする*/ 6 credit_sort(grade_data,n,comp_credit); 7 }else if(strcmp(argv[1],"gpa")==0){ 8 gpa_sort(grade_data,n,comp_gpa); 9 }else if(strcmp(argv[1],"name")==0){ 10 name_sort(grade_data,n,comp_name); 11 }else{ 12 printf("ソートしたいフィールドをcredit/gpa/nameの中から正しく選択してください。\n"); 13 }

のように書き換えてソートを実装したいのですが、それぞれのソート関数をどのように書けばよいのか全く見当がつかないので、ご教授いただけるとありがたいです。

また、比較関数は以下の通りです。

int comp_credit(const void *arg1,const void *arg2){ int x = ((SRec*)arg1)->credit; int y = ((SRec*)arg2)->credit; if ( x < y ) return -1; if ( y < x ) return 1; return 0; } int comp_gpa(const void *arg1,const void *arg2){ float x = ((SRec*)arg1)->gpa; float y = ((SRec*)arg2)->gpa; if ( x < y ) return -1; if ( y < x ) return 1; return 0; } int comp_name(const void *arg1,const void *arg2){ const char* x = ((SRec*)arg1)->name; const char* y = ((SRec*)arg2)->name; return strcmp(x,y); }

配列の挟み込み法を用いたソートプログラムは以下です。

void sort_func( int number[], int n ) { int k,m,x,y; for( k=1; k<n; ++k ) { x = number[k]; if( number[k-1] <= x )continue; for( m=0; m<k; ++m ) { if( number[m] >= x )break; /*mを見つけたらループ抜ける*/ } for( y=k; y>m; --y ) /*要素をずらしていく*/ { number[y] = number[y-1]; } number[m] = x; } printf("ソートを完了しました。\n"); }

考えているのは、
・比較関数での戻り値によって条件分岐し、それによって構造体の配列を挟み込み法でソートする
←比較関数の戻り値の受け取り方が分からない

という感じです。

よろしくおねがいします。

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

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

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

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

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

jimbe

2019/06/14 08:49

件名を「関数の戻り値の受け取り方が分からない」とされたほうが内容とあっているのではないでしょうか.
guest

回答4

0

引数に受けた関数ポインタの使い方がわからないという話なのであれば,
例えば下記のような簡単なのを書いて確認してみてはどうでしょう.

int f( int x ){ return 2 * x; } void Test( int (*pFunc)(int) ) { for( int x=0; x<5; ++x ) { int RetVal = pFunc( x ); //引数に渡された関数を使って,その戻り値を得る printf( "%d -> %d\n", x, RetVal ); } } int main(void) { Test( f ); return 0; }

投稿2019/06/14 07:33

fana

総合スコア11632

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

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

0

ひんと:

C

1void sort_func( int number[], int n, int (*comp)(const void*,const void*) ) { 2 int k,m,x,y; 3 int* px; 4 5 for( k=1; k<n; ++k ) { 6 x = number[k]; 7 if( comp(&number[k-1],&x) <= 0 )continue; 8 9 for( m=0; m<k; ++m ) { 10 if( comp(&number[m],&x) >= 0 )break; /*mを見つけたらループ抜ける*/ 11 } 12 for( y=k; y>m; --y ) { /*要素をずらしていく*/ 13 number[y] = number[y-1]; 14 } 15 number[m] = x; 16 } 17 printf("ソートを完了しました。\n"); 18} 19 20/* 21 おためし 22 */ 23#include <stdio.h> 24int compare(const void* px, const void* py) { 25 return *(const int*)px - *(const int*)py; 26} 27 28int main() { 29 int i; 30 int data[] = { 8, 6, 4, 2, 0, 9, 7, 5, 3, 1 }; 31 sort_func(data, 10, compare); 32 for ( i = 0; i < 10; ++i ) { 33 printf("%d ", data[i]); 34 } 35 return 0; 36}

投稿2019/06/14 10:16

編集2019/06/14 12:10
episteme

総合スコア16614

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

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

Kassy11

2019/06/18 07:54

ありがとうございました!
guest

0

ベストアンサー

C

1#include <stdio.h> 2 3typedef struct SRec { 4 int credit; 5 float gpa; 6 char name[32]; 7} SRec; 8 9SRec grade_data[3] = { 10 { 3, 6.6, "abc" }, 11 { 1, 7.7, "ghi" }, 12 { 2, 5.5, "def" }, 13}; 14 15void gpa_sort(SRec * grade_data, int n, int (*comp_gpa) (const void *, const void *)); 16void credit_sort(SRec * grade_data, int n, int (*comp_credit) (const void *, const void *)); 17void name_sort(SRec * grade_data, int n, int (*comp_name) (const void *, const void *)); 18 19int comp_credit(const void *arg1, const void *arg2) 20{ 21 int x = ((SRec *) arg1)->credit; 22 int y = ((SRec *) arg2)->credit; 23 if (x < y) return -1; 24 if (y < x) return 1; 25 return 0; 26} 27 28int comp_gpa(const void *arg1, const void *arg2) 29{ 30 float x = ((SRec *) arg1)->gpa; 31 float y = ((SRec *) arg2)->gpa; 32 if (x < y) return -1; 33 if (y < x) return 1; 34 return 0; 35} 36 37int comp_name(const void *arg1, const void *arg2) 38{ 39 const char *x = ((SRec *) arg1)->name; 40 const char *y = ((SRec *) arg2)->name; 41 return strcmp(x, y); 42} 43 44int main(int argc, char *argv[]) 45{ 46 if (argc != 2) { 47 printf("ソートしたいフィールド(credit/gpa/name)を引数で指定してください。\n"); 48 return 1; 49 } 50 const int n = sizeof grade_data / sizeof *grade_data; 51 if (strcmp(argv[1], "credit") == 0) 52 credit_sort(grade_data, n, comp_credit); 53 else if (strcmp(argv[1], "gpa") == 0) 54 gpa_sort(grade_data, n, comp_gpa); 55 else if (strcmp(argv[1], "name") == 0) 56 name_sort(grade_data, n, comp_name); 57 else { 58 printf("ソートしたいフィールドをcredit/gpa/nameの中から正しく選択してください。\n"); 59 return 2; 60 } 61 SRec *p = grade_data; 62 for (int i = 0; i < n; i++, p++) 63 printf("%4d %5.1f %s\n", p->credit, p->gpa, p->name); 64} 65 66void sort_func(SRec * grade_data, int n, int (*comp) (const void *, const void *)) 67{ 68 int k, m, y; 69 SRec x; 70 71 for (k = 1; k < n; ++k) { 72 x = grade_data[k]; 73 if (comp(&grade_data[k - 1], &x) <= 0) continue; 74 75 for (m = 0; m < k; ++m) { 76 if (comp(&grade_data[m], &x) >= 0) break; 77 } 78 for (y = k; y > m; --y) { 79 grade_data[y] = grade_data[y - 1]; 80 } 81 grade_data[m] = x; 82 } 83 printf("ソートを完了しました。\n"); 84} 85 86void gpa_sort(SRec * grade_data, int n, int (*comp_gpa) (const void *, const void *)) 87{ 88 sort_func(grade_data, n, comp_gpa); 89} 90 91void credit_sort(SRec * grade_data, int n, int (*comp_credit) (const void *, const void *)) 92{ 93 sort_func(grade_data, n, comp_credit); 94} 95 96void name_sort(SRec * grade_data, int n, int (*comp_name) (const void *, const void *)) 97{ 98 sort_func(grade_data, n, comp_name); 99}

sort_func を main から直接呼び出せば、gpa_sort、credit_sort、name_sort は不要です。

投稿2019/06/15 02:02

kazuma-s

総合スコア8224

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

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

Kassy11

2019/06/18 07:54

ありがとうございました、助かりました!
guest

0

C言語でコードを組む場合は、VisualStudioやEclipseなど、任意の行で実行を止め、変数の内容を確認できるようなデバッグ環境を整え、それで動作確認しながらコードを書いていけば、しょーもないケアレスミスが排除でき、コードの理解も早くできます

#まあ、どんな言語にも言えることですが

投稿2019/06/14 07:42

y_waiwai

総合スコア87719

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

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

fana

2019/06/14 07:56

「書き方(どう実装するのか)がわからん」という話に対する応答として,ちょっとずれていませんか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問