27

Cでcharへのポインタの配列があるとします。

char *data[5] = { "boda", "cydo", "washington", "dc", "obama" };

そして、qsortを使用してこの配列をソートしたいと思います。

qsort(data, 5, sizeof(char *), compare_function);

比較機能が思いつかない。何らかの理由でこれは機能しません:

int compare_function(const void *name1, const void *name2)
{
    const char *name1_ = (const char *)name1;
    const char *name2_ = (const char *)name2;
    return strcmp(name1_, name2_);
}

多くの検索を行ったところ**、qsort内で使用する必要があることがわかりました。

int compare_function(const void *name1, const void *name2)
{
    const char *name1_ = *(const char **)name1;
    const char *name2_ = *(const char **)name2;
    return strcmp(name1_, name2_);
}

そして、これは機能します。

*(const char **)name1誰かがこの関数での使用法を説明できますか?全くわかりません。なぜダブルポインタなのか?元の機能が機能しなかったのはなぜですか?

ありがとう、BodaCydo。

4

8 に答える 8

25

頭の中で物事をまっすぐに保つのに役立つ場合は、コンパレーターでポインターをキャストする必要があるタイプは、渡すデータポインターの元のタイプqsort(qsort docsが呼び出すbase)と同じです。しかし、一般的であるためには、「実際に」何であるかに関係なく、qsortすべてをとして処理します。void*

したがって、intの配列を並べ替える場合は、int*(に変換されたvoid*)を渡します。qsortはvoid*、コンパレータへの2つのポインタを返します。これをに変換し、逆参照して実際に比較する値int*を取得します。int

int今度は:に置き換えchar*ます

の配列を並べ替える場合は、 (に変換された)char*を渡します。qsortは、コンパレータへの2つのポインタを返します。これをに変換し、逆参照して実際に比較する値を取得します。char**void*void*char**char*

この例では、配列を使用しているため、char**渡すのは、char*最初の要素へのポインターへの「減衰」の配列の結果です。最初の要素は。であるためchar*、それへのポインタはchar**。です。

于 2010-08-15T22:47:14.873 に答える
3

あなたのデータがだったと想像してくださいdouble data[5]

比較メソッドは、要素(double)へのポインター(double *、void *として渡される)を受け取ります。
ここで、doubleをchar*に再度置き換えます。

于 2010-08-15T20:45:22.933 に答える
2

比較関数は、ソートする配列にあるオブジェクトのタイプへのポインターを取ります。配列にはが含まれているためchar *、比較関数はchar *、別名へのポインタを取りますchar **

于 2010-08-16T03:53:37.003 に答える
2

qsortポインタ以外のもので構成される配列をソートするのに十分一般的です。サイズパラメータがそこにあるのはそのためです。コンパイル時に配列要素の大きさがわからないため、配列要素を比較関数に直接渡すことはできません。したがって、ポインタを渡します。あなたの場合、、へのポインタを取得しchar *ますchar **

于 2010-08-15T20:45:58.683 に答える
0

からman qsort

The  contents of the array are sorted in ascending 
order according to a comparison function pointed to by
compar, which is called with two arguments that **point**
to the objects being compared.

したがって、比較関数は配列要素へのポインタを取得するように聞こえます。これで、aへのポインタchar *はa char ** (つまり、文字へのポインタへのポインタ)になります。

于 2010-08-15T20:49:56.890 に答える
0

char *data[5] = { "boda", "cydo", "washington", "dc", "obama" };

サイズ5の文字ポインターの配列をコンパイラーに要求するステートメントです。これらのポインターを文字列リテラルに初期化しましたが、コンパイラーにとっては、それでも5つのポインターの配列です。

その配列をに渡すとqsort、C配列パラメーターの受け渡し規則に従って、ポインターの配列が最初の要素を指すポインターに減衰します。

したがって、定数を含む実際の文字配列に到達する前に、1レベルの間接参照を処理する必要があります。

于 2010-08-15T20:50:43.837 に答える
0

@bodacydoは、他のプログラマーが伝えようとしていることを説明するプログラムですが、これは「整数」のコンテキストになります。

#include <stdio.h>


int main()
{
    int i , j;
    int *x[2] = {&i, &j};

    i = 10; j = 20;

    printf("in main() address of i = %p, address of j = %p \r\n", &i, &j);

    fun(x);
    fun(x + 1);

    return 0;
}


void fun(int **ptr)
{
    printf("value(it would be an address) of decayed element received = %p, double dereferenced value is %d \r\n",*ptr, **ptr);
    printf("the decayed value can also be printed as *(int **)ptr = %p \r\n", *(int **)ptr );
}
于 2017-01-06T04:13:11.247 に答える
0

たぶん、私からのコード例を提供する方が簡単です。TreeNodeの配列を並べ替えようとしていますが、コンパレータの最初の数行は次のようになっています。

int compareTreeNode(const void* tt1, const void* tt2) {
   const TreeNode *t1, *t2;
   t1=*(const TreeNode**)tt1;
   t2=*(const TreeNode**)tt2;

その後、t1とt2を使用して比較を行います。

于 2019-01-21T07:49:27.637 に答える