C言語の標準関数を目的別に調べることができる辞典

ホーム > C 標準関数逆引き辞典 > データ構造 <配列> > 配列の要素をソートする

C 標準関数逆引き辞典

:: reverse dictionary ::

文字列

※ソースファイルについて


配列の要素をソートする

配列の要素をソートするには、qsort 関数を使います。

≪宣言≫

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <search.h>

#define STR_MAX  256  /* 文字列の最大長 */

/* 比較関数 */
int strcmp_asc(const void *, const void *);
int strcmp_desc(const void *, const void *);
int main(void)
{
  /* ソートするデータ */
  char systems[][STR_MAX] =
  {
      "Windows"
    , "ウィンドウズ"
    , "Linux"
    , "リナックス"
    , "Solaris"
    , "ソラリス"
  };

  int i;
  int length;

  /* 要素数を求める */
  length = sizeof(systems) / STR_MAX;

  /* 昇順でソート */
  qsort(systems, length, STR_MAX, strcmp_asc);

  printf("▼昇順\n");
  for (i = 0; i < length; i++)
  {
    printf("systems[%d]=%s\n", i, systems[i]);
  }

  /* 降順でソート */
  qsort(systems, length, STR_MAX, strcmp_desc);

  printf("▼降順\n");
  for (i = 0; i < length; i++)
  {
    printf("systems[%d]=%s\n", i, systems[i]);
  }

  return EXIT_SUCCESS;
}

/**
 * 文字列を辞書式順序の昇順で比較します。
 * @param sa 比較する文字列
 * @param sb 比較する文字列
 * @return sa が sb と等しい場合は 0 、
 *         sa が sb より小さい場合は -1 以下、
 *         sa が sb より大きい場合は 1 以上
 */
int strcmp_asc(const void *sa, const void *sb)
{
  return strcmp((char *)sa, (char *)sb);
}

/**
 * 文字列を辞書式順序の降順で比較します。
 * @param sa 比較する文字列
 * @param sb 比較する文字列
 * @return sa が sb と等しい場合は 0 、
 *         sa が sb より小さい場合は 1 以上、
 *         sa が sb より大きい場合は -1 以下
 */
int strcmp_desc(const void *sa, const void *sb)
{
  return strcmp((char *)sb, (char *)sa);
}

ソースファイル

次のような出力になります。

▼昇順
systems[0]=Linux
systems[1]=Solaris
systems[2]=Windows
systems[3]=ウィンドウズ
systems[4]=ソラリス
systems[5]=リナックス
▼降順
systems[0]=リナックス
systems[1]=ソラリス
systems[2]=ウィンドウズ
systems[3]=Windows
systems[4]=Solaris
systems[5]=Linux

▼ 関数

void qsort(void *a, size_t n, size_t sz,
           int (__cdecl *cf)(const void *ea, const void *eb))

配列 a の要素 n 個をソートします。
sz には、要素のサイズ(バイト数)を指定します。

ソートの際、比較関数 cf が呼び出されます。
cf には、独自に作成した比較関数を指定します。

比較関数は、2つの引数を取るように作成します。
引数の型は、void ポインタ( const void * )です。

ここでは説明のため、その引数を eaeb とします。 この eaeb に比較する要素が渡されるので、それを比較した値を返すようにします。

昇順でソートする場合、返す値は次のようになります。

  • eaeb と等しい … 0
  • eaeb より小さい( ea < eb ) … -1 以下(負)
  • eaeb より大きい( ea > eb ) … 1 以上(正)

降順でソートする場合は、昇順の正と負を逆にします。

  • eaeb より小さい( ea < eb ) … 1 以上(正)
  • eaeb より大きい( ea > eb ) … -1 以下(負)

昇順と降順の比較関数を用意することで、両方のソートに対応できます。

●引数

a … ソートする配列
n … ソートする要素の個数
sz … 要素のサイズ(バイト数)
cf … 比較関数

●補足1

ソートには、クイックソートのアルゴリズムが適用されます。

●補足2

比較関数 cf の戻り値は、文字列比較関数の戻り値と同じです。

要素が文字列であれば、通常は文字列比較関数を cf から呼び出すだけで済みます。

●補足3

文字列の配列だけでなく、他の型の配列もソートできます。

次の3つの例を挙げておきます。


[例1] ワイド文字列の配列をソート

≪宣言≫

#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <search.h>

#define STR_MAX  256  /* 文字列の最大長 */

/* 比較関数 */
int wcscmp_asc(const void *, const void *);
int wcscmp_desc(const void *, const void *);
int main(void)
{
  /* ソートするデータ */
  wchar_t systems[][STR_MAX] =
  {
      L"Windows"
    , L"ウィンドウズ"
    , L"Linux"
    , L"リナックス"
    , L"Solaris"
    , L"ソラリス"
  };

  int i;
  int length;
  int datasize = sizeof(wchar_t) * STR_MAX;

  setlocale(LC_ALL, "ja");  /* ロケールを日本語に設定 */

  /* 要素数を求める */
  length = sizeof(systems) / datasize;

  /* 昇順でソート */
  qsort(systems, length, datasize, wcscmp_asc);

  wprintf(L"▼昇順\n");
  for (i = 0; i < length; i++)
  {
    wprintf(L"systems[%d]=%s\n", i, systems[i]);
  }

  /* 降順でソート */
  qsort(systems, length, datasize, wcscmp_desc);

  wprintf(L"▼降順\n");
  for (i = 0; i < length; i++)
  {
    wprintf(L"systems[%d]=%s\n", i, systems[i]);
  }

  return EXIT_SUCCESS;
}

/**
 * ワイド文字列を辞書式順序の昇順で比較します。
 * @param sa 比較するワイド文字列
 * @param sb 比較するワイド文字列
 * @return sa が sb と等しい場合は 0 、
 *         sa が sb より小さい場合は -1 以下、
 *         sa が sb より大きい場合は 1 以上
 */
int wcscmp_asc(const void *sa, const void *sb)
{
  return wcscmp((wchar_t *)sa, (wchar_t *)sb);
}

/**
 * ワイド文字列を辞書式順序の降順で比較します。
 * @param sa 比較するワイド文字列
 * @param sb 比較するワイド文字列
 * @return sa が sb と等しい場合は 0 、
 *         sa が sb より小さい場合は 1 以上、
 *         sa が sb より大きい場合は -1 以下
 */
int wcscmp_desc(const void *sa, const void *sb)
{
  return wcscmp((wchar_t *)sb, (wchar_t *)sa);
}

ソースファイル

次のような出力になります。

▼昇順
systems[0]=Linux
systems[1]=Solaris
systems[2]=Windows
systems[3]=ウィンドウズ
systems[4]=ソラリス
systems[5]=リナックス
▼降順
systems[0]=リナックス
systems[1]=ソラリス
systems[2]=ウィンドウズ
systems[3]=Windows
systems[4]=Solaris
systems[5]=Linux

[例2] 整数の配列をソート

≪宣言≫

#include <stdio.h>
#include <stdlib.h>
#include <search.h>

/* 比較関数 */
int numcmp_asc(const void *, const void *);
int numcmp_desc(const void *, const void *);
int main(void)
{
  /* ソートするデータ */
  int nums[] = {100, 2, 200, 1, 20, 10};

  int i;
  int length;
  int datasize = sizeof(int);

  /* 要素数を求める */
  length = sizeof(nums) / datasize;

  /* 昇順でソート */
  qsort(nums, length, datasize, numcmp_asc);

  printf("▼昇順\n");
  for (i = 0; i < length; i++)
  {
    printf("nums[%d]=%d\n", i, nums[i]);
  }

  /* 降順でソート */
  qsort(nums, length, datasize, numcmp_desc);

  printf("▼降順\n");
  for (i = 0; i < length; i++)
  {
    printf("nums[%d]=%d\n", i, nums[i]);
  }

  return EXIT_SUCCESS;
}

/**
 * 数値を昇順で比較します。
 * @param na 比較する数値
 * @param nb 比較する数値
 * @return na が nb と等しい場合は 0 、
 *         na が nb より小さい場合は -1 以下、
 *         na が nb より大きい場合は 1 以上
 */
int numcmp_asc(const void *na, const void *nb)
{
  return *(int *)na - *(int *)nb;
}

/**
 * 数値を降順で比較します。
 * @param na 比較する数値
 * @param nb 比較する数値
 * @return na が nb と等しい場合は 0 、
 *         na が nb より小さい場合は 1 以上、
 *         na が nb より大きい場合は -1 以下
 */
int numcmp_desc(const void *na, const void *nb)
{
  return *(int *)nb - *(int *)na;
}

ソースファイル

次のような出力になります。

▼昇順
nums[0]=1
nums[1]=2
nums[2]=10
nums[3]=20
nums[4]=100
nums[5]=200
▼降順
nums[0]=200
nums[1]=100
nums[2]=20
nums[3]=10
nums[4]=2
nums[5]=1

[例3] 構造体の配列をソート

≪宣言≫

#include <stdio.h>
#include <stdlib.h>
#include <search.h>

#define STR_MAX  256  /* 文字列の最大長 */

/* 比較関数 */
int scorecmp_desc(const void *, const void *);

/* プレイヤーの情報 */
typedef struct player
{
  char name[STR_MAX];  /* 名前 */
  long score;          /* 得点 */
} Player;
int main(void)
{
  /* ソートするデータ */
  Player players[] = {
          {"田中", 32100}
        , {"鈴木", 78900}
        , {"山田", 45000}
        , {"佐藤", 60000}
  };

  int i;
  int length;
  int datasize = sizeof(Player);

  /* 要素数を求める */
  length = sizeof(players) / datasize;

  /* 得点の降順でソート */
  qsort(players, length, datasize, scorecmp_desc);

  printf("▼得点の降順\n");
  printf("[名前]  [得点]\n");
  for (i = 0; i < length; i++)
  {
    printf("%s    %d\n", players[i].name, players[i].score);
  }

  return EXIT_SUCCESS;
}

/**
 * 得点の降順で比較します。
 * @param pa 比較するプレイヤー
 * @param pb 比較するプレイヤー
 * @return pa の得点が pb の得点と等しい場合は 0 、
 *         pa の得点が pb の得点より小さい場合は 1 以上、
 *         pa の得点が pb の得点より大きい場合は -1 以下
 */
int scorecmp_desc(const void *pa, const void *pb)
{
  return ((Player *)pb)->score - ((Player *)pa)->score;
}

ソースファイル

次のような出力になります。

▼得点の降順
[名前]  [得点]
鈴木    78900
佐藤    60000
山田    45000
田中    32100

注目キーワード ベスト5

  1. セキュリティ
  2. ホスティング
  3. レンタルサーバ
  4. ファイル復旧
  5. ハードディスク修復

データ構造 <配列> - array -


ホーム > C 標準関数逆引き辞典 > データ構造 <配列> > 配列の要素をソートする

Copyright (C) 2005-2007 Noto Watabe. All rights reserved.
e-mail:wmh@always-pg.com