1

私は現在、小さなソート機能を書いています。私は stdio ライブラリしか使えないので、'独自の strcmp' 関数を書きました。

int ownstrcmp(char a[], char b[])
{
   int i = 0;

   while( a[i] == b[i] )  
   {

      if( a[i] == '\0' ) 
        return 0;
      ++i;
   }

   return  ( a[i] < b[i]) ? 1 : -1;
}

これは私にとってとてもうまくいきます。しかし、小さな問題が 1 つあります。「非標準文字」に対して何ができますか? "ä,ü,ß のように、それらの 10 進 ASCII 値は通常の文字よりも大きいため、文字列 'example' を 'ääää' の後ろに並べ替えます。ロケールについては既に読みましたが、使用できる唯一のライブラリはstdio.h. ありますか?この問題の「簡単な」解決策は?

4

5 に答える 5

1

文字のエンコーディングを把握し、文字列を適切に処理する必要があります。エンコーディングがマルチバイトの場合、バイトではなく個々の文字の読み取り (および比較) を開始する必要があります。

また、国際的に文字を比較する方法はロケールによって異なり、単一の解決策はありません。一部の言語では、「ä」は「z」の後にソートされ、一部の言語では「a」のすぐ隣にソートされます。

これを実装する簡単な方法の 1 つは、もちろん、次のように、各文字の相対的な順序を保持するテーブルを作成することです。

unsigned char character_order[256];

character_order[(unsigned char) 'a'] = 1;
character_order[(unsigned char) 'ä'] = character_order[(unsigned char) 'a'];
/* ... and so on ... */

次に、文字のエンコードされた値 (文字の並べ替え順序の "プロキシ" として使用できなくなります) を減算する代わりに、character_order値を比較します。

上記では、配列サイズが 256 しかないため、シングルバイト エンコーディング、つまり Latin-1 などを想定しています。

unsigned charまた、文字リテラルで索引付けする場合のキャストにも注意してください。

于 2013-01-08T09:03:34.660 に答える
1

ドイツ語の場合、ウムラウト ä、ö、ü、および ß は、「展開された」形式であるかのようにソートされます。

ä -> ae
ö -> oe
ü -> ue
ß -> ss

標準に従って照合を取得するには、比較する前に文字列を展開できます。

于 2013-01-08T09:20:54.657 に答える
1

あなたの質問はやや漠然としています。まず、ウムラウト付きの文字がどのように表現されるかは、エンコーディングによって異なります。たとえば、私のコンピューターのロケールはギリシャ語に設定されています。これは、これらの特殊なラテン文字の代わりにギリシャ語の文字を使用していることを意味します。私が知る限り、そのようなことは想定できません。

第二に、あなたの質問への答えはあなたの表現に依存します。まだ「char1 文字に 1 つ」の表現を使用していますか? その場合、上記のコードは引き続き機能する可能性があります。

複数のchar表現を使用している場合、たとえばchar1 文字あたり 2 つの の場合、コードを変更して、2 つの連続 charした がのときに終了するようにする必要があります\0

wchar_t一般に、関数のファミリー (特にwcscmp) がどのように実装されているかを調べたいと思うかもしれません。

于 2013-01-08T09:08:33.933 に答える
0

ドイツ語の通常のエンコーディングであるISO/IEC_8859-16エンコーディングを使用している場合はcharunsigned char.

このようにして、文字は 0 ~ 255 の間隔で表すことができ、この標準に適しています。

于 2013-01-08T09:14:48.070 に答える
0

UTF8 では、コードに従って、これが役立ちます

if ((a[i] > 0) ^ (b[i] > 0))
    return a[i] > 0 ? 1 : -1;
else
    return a[i] < b[i] ? 1 : -1;

ただし、次のようなケースを確認する必要がありますownstrcmp("ab", "abc");

strcmp()さらに、あなたのコードは次のようには機能しません<string.h>

ゼロより大きい値は、一致しない最初の文字の値が str2 よりも str1 の方が大きいことを示します。ゼロ未満の値はその反対を示しま​​す。

私は次のようにします:

int ownstrcmp(char a[], char b[])
{
    int i = 0;

    while(a[i] == b[i]) {
        if (a[i] == 0) return 0;
        ++i;
    }
    if ((a[i] == 0) || (b[i] == 0))
        return a[i] != 0 ? 1 : -1;
    if ((a[i] > 0) ^ (b[i] > 0))
        return a[i] < 0 ? 1 : -1;
    else
        return a[i] > b[i] ? 1 : -1;
}
于 2013-01-08T10:56:08.110 に答える