22

次のように C 文字列比較関数を呼び出すと、次のようになります。

strcmp("time","time")

これは、文字列が等しくないことを意味する 0 を返します。

Cの実装がこれを行うように見える理由を誰か教えてもらえますか? 等しい場合、ゼロ以外の値を返すと思います。この動作が見られる理由に興味があります。

4

7 に答える 7

31

strcmpは、パラメーターとして指定した2つの文字列の字句の違い(または「短絡シリアルバイトコンパレータ」と呼ぶ必要がありますか?:-))を返します。0は、両方の文字列が等しいことを意味します

正の値は、辞書でs1がs2の後にあることを意味します。

負の値は、辞書でs1がs2の前にあることを意味します。

したがって、明らかに異なる「時間」と「お金」を比較するときのゼロ以外の値は、時間はお金であると言われるかもしれませんが!:-)

于 2009-02-27T16:25:40.677 に答える
17

このような実装の良い点は、次のように言えることです。

if(strcmp(<stringA>, <stringB>) > 0)   // Implies stringA > stringB
if(strcmp(<stringA>, <stringB>) == 0)  // Implies stringA == stringB
if(strcmp(<stringA>, <stringB>) < 0)   // Implies stringA < stringB
if(strcmp(<stringA>, <stringB>) >= 0)  // Implies stringA >= stringB
if(strcmp(<stringA>, <stringB>) <= 0)  // Implies stringA <= stringB
if(strcmp(<stringA>, <stringB>) != 0)  // Implies stringA != stringB

0 との比較が含意の比較と正確に一致することに注意してください。

于 2009-02-27T17:09:29.290 に答える
6

関数は、一般的なケース (または独自のケース) に対してゼロを返し、特別なケースに対して非ゼロを返すのが一般的です。main 関数を例にとると、通常、成功するとゼロが返され、失敗するとゼロ以外の値が返されます。ゼロ以外の正確な値は、何が問題だったかを示します。例: メモリ不足、アクセス権がないなど。

あなたの場合、文字列が等しい場合、文字列に同じ文字が含まれている以外に等しい理由はありません。ただし、それらが等しくない場合は、最初の値が小さくなるか、2 番目の値が小さくなる可能性があります。等しい場合は 1、小さい場合は 0、大きい場合は 2 を返すのは、どういうわけか奇妙だと思います。

引き算で考えることもできます。

return = s1 - s2

s1 が「辞書的に」小さい場合は、負の値になります。

于 2009-02-27T16:55:11.040 に答える
4

コードを返すもう 1 つの理由strcmp()は、標準ライブラリの function で直接使用できるようにするためです。これqsort()により、文字列の配列を並べ替えることができます。

#include <string.h> // for strcmp()
#include <stdlib.h> // for qsort()
#include <stdio.h>

int sort_func(const void *a, const void *b)
{
    const char **s1 = (const char **)a;
    const char **s2 = (const char **)b;
    return strcmp(*s1, *s2);
}

int main(int argc, char **argv)
{
    int i;
    printf("Pre-sort:\n");
    for(i = 1; i < argc; i++)
        printf("Argument %i is %s\n", i, argv[i]);
    qsort((void *)(argv + 1), argc - 1, sizeof(char *), sort_func);
    printf("Post-sort:\n");
    for(i = 1; i < argc; i++)
        printf("Argument %i is %s\n", i, argv[i]);
    return 0;
}

この小さなサンプル プログラムは、その引数を ASCIIbetically (字句的に呼び出すもの) に並べ替えます。見た目:

$ gcc -o sort sort.c
$ ./sort hi there little fella
Pre-sort:
Argument 1 is hi
Argument 2 is there
Argument 3 is little
Argument 4 is fella
Post-sort:
Argument 1 is fella
Argument 2 is hi
Argument 3 is little
Argument 4 is there

等しい文字列に対して (true) がstrcmp()返され、等しくない文字列に対して (false) が返された場合、2 つの文字列間の不等の程度または方向(つまり、どの程度異なるか、どちらが大きいか) を取得するために使用することは不可能です。ソート機能としては使えません。10

あなたが C にどの程度精通しているかはわかりません。上記のコードでは、C の最も紛らわしい概念 (ポインター演算、ポインターの再キャスト、関数ポインター) を使用しています。時間内に到着します。それまでは、StackOverflow に関する楽しい質問がたくさんあります。;)

于 2009-09-02T04:58:48.077 に答える
3

あなたはstrcmp(仮説)のように働きたいようです

int isEqual(const char *, const char *)

それが整数結果の「ゼロは偽」の解釈に当てはまることを確認するためですが、2 つの文字列が同じではないことが確立されたとしても、どちらが「先に来たか」を学習する必要があるため、並べ替えのロジックが複雑になります。 "。

さらに、一般的な実装は次のようになると思います

int strcmp(const char *s1, const char *s2){
   const unsigned char *q1=s1, *q2=s2;
   while ((*q1 == *q2) && *q1){ 
      ++q1; ++q2; 
   };
   return (*q1 - *q2);
}

[編集:ちょっと] K&Rのような方法でエレガントです. ここで重要なポイント (コードを正しく作成することでますますあいまいになります (明らかに、私は十分に放っておくべきでした)) は、return ステートメントの方法です。

   return (*q1 - *q2);

これにより、文字値に関して自然に比較結果が得られます。

于 2009-02-27T16:53:25.523 に答える
2

3 つの結果が考えられます。文字列 1 が文字列 2 の前に来る、文字列 1 が文字列 2 の後に来る、文字列 1 は文字列 2 と同じです。これら 3 つの結果を分けておくことが重要です。strcmp() の用途の 1 つは、文字列のソートです。問題は、これら 3 つの結果にどのように値を割り当てたいか、そしてどのように物事を多かれ少なかれ一貫性を保つかです。また、strcmp() のような比較関数を必要とする qsort() および bsearch() のパラメーターを確認することもできます。

文字列等価関数が必要な場合、true と false に関する C の規則に従って、等しい文字列に対してはゼロ以外を返し、等しくない文字列に対してはゼロを返します。これは、文字列 1 が文字列 2 の前または後に来たかどうかを区別する方法がないことを意味します。int や名前を付けたい他の C データ型には複数の true 値がありますが、false は 1 つだけです。

したがって、文字列の等価性に対して true を返す便利な strcmp() を用意するには、言語の残りの部分に多くの変更を加える必要がありますが、それは実現しません。

于 2009-02-27T17:25:53.620 に答える
0

単に対称性のためだと思います: 少ない場合は -1、等しい場合は 0、多い場合は 1 です。

于 2009-02-27T16:57:22.423 に答える