Thinkers'Studio
JavaとC言語の自習ツール
qsort でソートするプログラム例

 今回は、qsort を使ってソートするプログラム例です。
 qsort はいろいろな配列をいろいろな条件でソートすることができますが、下記では int 配列を昇順にソートします。

qsort の形式

  void qsort( void *base, size_t n, size_t size, 
              int (*comp)(const void *, const void *) )
 ひとつの要素の大きさが size である n個の要素をソートします。要素の先頭は base に指定します。 comp には比較用の関数へのポインタを指定します。 qsort は実行時に、比較したい2つの要素を指すポインタを関数 comp に渡して大小を調べます。

qsort の比較用の関数は

 void へのポインタ2つを引数に取るもので、戻り値は両要素の大小の判定結果を示します。 第1引数 > 第2引数のとき正の値を戻すようにすると、昇順のソートになります。

qsort を使ったプログラム例 】
 int の ages 配列を昇順にソートします。つまり、年令の若い順に並べ替えます。
#include <stdio.h>
#include <stdlib.h>

// -- 比較用の関数 cmp --
int cmp( const void *p, const void *q ) {
    return *(int*)p - *(int*)q;
}
// ---------------------------------------
main()
{
    int ages[] = { 21, 18, 53, 43, 14, 24, 38 };
    int n, i;

    n = sizeof( ages )/sizeof( int );
    qsort( ages, n, sizeof(int), cmp );
    for( i = 0; i < n; i++ )
        printf( "ages[%d] = %d\n", i, ages[i] );
}
実行結果
ages[0] = 14
ages[1] = 18
ages[2] = 21
ages[3] = 24
ages[4] = 38
ages[5] = 43
ages[6] = 53

 cmp では、比較するものが int型の配列要素だと分かっているので、void へのポインタ p と q を int へのポインタにキャストして比べています。 return *(int*)p - *(int*)q と書くだけで、昇順ソートの比較結果を返すことができます。たとえば 21 と 18 の比較なら正の値 3 が、18 と 53 の比較なら -35 の負の値が返ります。それを見て、必要なら qsort が並べ替えます。
 qsort がその本領を発揮するのは構造体のソートです。 それはまた別の Tips で。

(今週のクイズです)
 double 型配列をソートする場合、cmp関数もそれに合わせたものにしなければなりません。
 下記は、int型用cmp の (int*) を単純に (double*) へ置き換えたものです。
int cmp( const void *p, const void *q ) {
    return *(double*)p - *(double*)q;  //NG!
}
 これは正しくありません。なぜでしょう? また、どのような比較をすればよいでしょう?
  (答えは、次回のC言語の Tips で ・・・)

[ 関連記事 ] 構造体配列をqsort, ポインタ配列をqsort
[ ご案内 ] ポインタの要点を学習できるコース:要点講座 [配列とポインタ編]

前回の答え:(前回の問題を見る
  char  *dayname[]   ・・・ 定数文字列が取られ、その領域へのポインタの配列。
  char  dayname[][8] ・・・ char配列の配列。[]内に指定したサイズで取られます。
上は、文字列+'\0'分のピッタリサイズで取られます。定数扱いなので文字列の内容を変えられません。下は、サイズを超えなければ書き換え可能です。