C言語入門(38) 実際にプログラムを読んで理解を深めよう ls編(12)

Posted: 2013年05月02日

前回まで、表示関数を解説してきました。
今回はソート関数を解説していきます。

ソート関数は表示関数同様に
フラグに応じて呼び出される処理が変化します。

ls.c main関数です。

    /* Select a sort function. */
    if (f_reversesort) {
        if (!f_timesort && !f_sizesort)
            sortfcn = revnamecmp;
        else if (f_sizesort)
            sortfcn = revsizecmp;
        else if (f_accesstime)
            sortfcn = revacccmp;
        else if (f_birthtime)
            sortfcn = revbirthcmp;
        else if (f_statustime)
            sortfcn = revstatcmp;
        else        /* Use modification time. */
            sortfcn = revmodcmp;
    } else {
        if (!f_timesort && !f_sizesort)
            sortfcn = namecmp;
        else if (f_sizesort)
            sortfcn = sizecmp;
        else if (f_accesstime)
            sortfcn = acccmp;
        else if (f_birthtime)
            sortfcn = birthcmp;
        else if (f_statustime)
            sortfcn = statcmp;
        else        /* Use modification time. */
            sortfcn = modcmp;
    }

先頭から順に解説していきます。
今回は、revnamecmp関数です。

cmp.c revnamecmp関数です。

プログラムプログラム:

int
revnamecmp(const FTSENT *a, const FTSENT *b)
{

    return (strcoll(b->fts_name, a->fts_name));
}

解説解説:

比較関数なので
文字列の比較は、シンプルに作れます。

strcollでfts_name(ファイル名)を比較しています。

では、どのようにこの関数が呼ばれるのでしょうか

ls.c traverse関数です。

    if ((ftsp =
        fts_open(argv, options, f_nosort ? NULL : mastercmp)) == NULL)
        err(1, "fts_open");

解説解説:

fts_openの引数で
比較関数を渡します。
その比較関数はどのようになっているか

ls.c mastercmp関数です。

/*
 * Ordering for mastercmp:
 * If ordering the argv (fts_level = FTS_ROOTLEVEL) return non-directories
 * as larger than directories.  Within either group, use the sort function.
 * All other levels use the sort function.  Error entries remain unsorted.
 */
static int
mastercmp(const FTSENT * const *a, const FTSENT * const *b)
{
    int a_info, b_info;

    a_info = (*a)->fts_info;
    if (a_info == FTS_ERR)
        return (0);
    b_info = (*b)->fts_info;
    if (b_info == FTS_ERR)
        return (0);

    if (a_info == FTS_NS || b_info == FTS_NS)
        return (namecmp(*a, *b));

    if (a_info != b_info &&
        (*a)->fts_level == FTS_ROOTLEVEL && !f_listdir) {
        if (a_info == FTS_D)
            return (1);
        if (b_info == FTS_D)
            return (-1);
    }
    return (sortfcn(*a, *b));
}

解説解説:

この関数では、基本的なソート処理が実装されています。

最後に関数ポインターで設定された比較関数を呼び出します。

この関数ポインターは、グローバル変数として定義されているため
ここでいきなり使用することができます。

エラーチェックくらいしてもいいと思いますが

この関数では、具体的にどのような処理が行われているか

  • 引数の値が無効ではないか
  • 引数の値がファイル名の場合は、文字列の比較を行う
  • 引数の値がフォルダの場合は、ファイルよりも先頭にソートさせる

以上のことを行なっています。

カテゴリー: プログラム, 入門 | タグ: , , | コメント無し »

コメント