質問

理由のために、私は完全に同意しませんが、「私の反対意見を続けている(反用性の)力は、私の異議にもかかわらず、基本的なstrcmp()をその名前で比較するソートルーチンを持っています。うまく機能します。それを間違えるのは難しいです。ただし、11時間目には、ASCIIの注文に反して、文字で始まるエントリの後に数字から始まるエントリが来ることが決定されました。彼らは、eBCDIC規格には文字に続く数字があるため、以前の仮定は普遍的な真実ではなく、私はこの議論に勝つ力はありません...しかし、私は脱線します。

そこに私の問題があります。 STRCMPへのすべての適切な参照を新しい関数呼び出しに置き換えましたnonstd_strcmpを呼び出しましたが、ソート変更を達成するために変更を実装する必要があります。私は自分のベースとしてFreeBSDソースを使用しました: http://freebsd.active-venture.com/freebsd-srctree/newsrc/libkern/strncmp.c.html

 if (n == 0)
  return (0);
 do {
  if (*s1 != *s2++)
   return (*(const unsigned char *)s1 -
    *(const unsigned char *)(s2 - 1));
  if (*s1++ == 0)
   break;
 } while (--n != 0);
 return (0);

私はそれがどのように行われるべきかを本当に考えるために少し時間を取る必要があるかもしれないと思いますが、私は私だけがリリース前にちょうどリリースの仕様の変更の脳死を経験したのは私だけではないと確信しています。

役に立ちましたか?

解決

この特別な場合 それだけ 大文字(コメントでOPで言及されている)と数字0-9では、注文表を省略し、両方の異なる文字を4を掛け、結果測定値256を比較することもできます。オーバーフロー8ビット(57×4 = 228)ではなく、大文字の範囲(65〜90)は(65×4 = 260)になります。乗算値Modulo 256を比較すると、各文字の値は任意の数字の値よりも少なくなります:90×4%256 = 104 <192 = 48×4

コードは次のように見えるかもしれません:

int my_strcmp (const char *s1, const char *s2) {
    for (; *s1 == *s2 && *s1; ++s1, ++s2);
    return (((*(const unsigned char *)s1) * 4) & 0xFF) - \
           (((*(const unsigned char *)s2) * 4) & 0xFF);
}

もちろん、注文テーブルソリューションは一般的にはるかに汎用性があります。これにより、すべての文字のソートオーダーを定義できるため、このソリューションはこの特別なケースでのみ賢明です。 大文字 文字vs数字。 (しかし、マイクロコントローラープラットフォームでは、テーブルで使用される少量のメモリさえも保存することは、本当の利点になる可能性があります。)

他のヒント

あなたがする必要があるのは、各文字の注文テーブルを作成することです。これは、ケースに依存しない比較も行う最も簡単な方法でもあります。

if (order_table[*s1] != order_table[*s2++])

キャラクターに署名される可能性があることに注意してください。その場合、テーブルのインデックスはネガティブになる可能性があります。このコードは、署名された文字のみを対象としています。

int raw_order_table[256];
int * order_table = raw_order_table + 128;
for (int i = -128;  i < 128;  ++i)
    order_table[i] = (i >= '0' && i <= '9') ? i + 256 : toupper(i);

あなたの力が他のすべての力と同じであるなら、私が遭遇することになった場合、あなたはそれを選択肢にしたいかもしれません(たとえそれが隠されていても):

ソートオーダー:

o文字の後の数

o数字後の文字

またはさらに悪いことに、彼らは数字を数値的にソートしたいと思うかもしれません(例:「A123」が来る 「a15」)、それは可能です

o文字の後の数

o数字後の文字

o文字後のスマート数

oスマート番号の後の文字

これは、症状ではなく、実際の問題を診断することになります。 11時間59分に彼らが心を変える可能性がわずかにあるに違いない。

ルックアップテーブルを使用して、文字を比較するときにASCIIをEBCDICに翻訳することができます;-)

上記の回答と一般的に合意している間、ほとんどの比較が異なる最初の文字を持っていると思わない限り、ループのすべての反復を検索するのはばかげていると思います。

char c1, c2;
while((c1 = *(s1++)) == (c2 = *(s2++)) && c1 != '\0');
return order_table[c1] - order_table[c2];

また、静的初期イザーを使用してOrder_tableを構築することをお勧めします。

以下は、他の投稿で説明されているものと同様の文字列比較のかなり良い実装である必要があります。

static const unsigned char char_remap_table[256] = /* values */

#define char_remap(c) (char_remap_table[(unsigned char) c])

int nonstd_strcmp(const char * restrict A, const char * restrict B) {
     while (1) {
          char a = *A++;
          char b = *B++;
          int x = char_remap(a) - char_remap(b);
          if (x) {
               return x;
          }
          /* Still using null termination, so test that from the original char,
           * but if \0 maps to \0 or you want to use a different end of string
           * then you could use the remapped version, which would probably work
           * a little better b/c the compiler wouldn't have to keep the original
           * var a around. */
          if (!a) { /* You already know b == a here, so only one test is needed */
               return x;  /* x is already 0 and returning it allows the compiler to
                           * store it in the register that it would store function
                           * return values in without doing any extra moves. */
          }
     }
}

それを超えて、関数を一般化して、char_remap_tableをパラメーターとして使用することができます。これにより、必要に応じて後で異なるマッピングを簡単に使用できるようになります。

int nonstd_strcmp(const char * restrict a, const char * restrict b, const char * restrict map);
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top