このCコードでアルファベットが複数の範囲に分割されるのはなぜですか?


161

カスタムライブラリで実装を見ました:

inline int is_upper_alpha(char chValue)
{
    if (((chValue >= 'A') && (chValue <= 'I')) ||
        ((chValue >= 'J') && (chValue <= 'R')) ||
        ((chValue >= 'S') && (chValue <= 'Z')))
        return 1;
    return 0;
}

それはイースターエッグですか、それとも標準のC / C ++メソッドと比較した場合の利点は何ですか?

inline int is_upper_alpha(char chValue)
{
    return ((chValue >= 'A') && (chValue <= 'Z'));
}

EBCDICでは、小文字の文字範囲が大文字の文字範囲の前にあり、どちらも数字の前にあることに注意してください。これは、ASCIIベースのエンコーディング(8859など)の順序とは正反対です。 xシリーズ、またはUnicode、またはCP1252、または…)。
Jonathan Leffler、2015年

1
注:場合'J' - 'I''S' - 'R'両方同じ1、私は合理的なオプティマイザは後者で、前者を回すだろうと期待しています。
Matthieu M.15年

回答:


214

このコードの作成者はおそらく、ある時点でEBCDICをサポートする必要があり、そこでは文字の数値が不連続です(ご想像のとおりIJR、の間にギャップが存在Sします)。

CおよびC ++標準では、この理由により文字が連続した数値09持つことしか保証されていないため、これらのメソッドはどちらも厳密に標準に準拠していません。


64
実際のWTFは、元の作者がコメントを付けなかった理由です// In the EBCDIC coding, the alphabet has gaps between these values. See URL: xxxx for details。そうすれば、質問をする必要さえありません。答えはコードに組み込まれています。
アベレンキー

66
@abelenkyコードが元々ebcdicが通常使用されているシステム用であった場合、その時点では明白でコメントは必要ないように思われるかもしれませんが、残念ながら、レガシーコードで問題がなかったように見えるのは今は奇妙に見えます。
Vality

26
@abelenky:実際の WTFは、元の作成者が標準機能を使用しなかった理由return ( isalpha( chValue ) && isupper( chValue ) )です。つまり、...
DevSolar

4
@デーモン:それは問題ではありません。ネイティブでそのエンコーディングを使用しないシステムでも、「エイリアン」エンコーディングを処理する必要があるかもしれません。したがって、ロケールを特定のエンコーディングに設定し、プログラマが上記のような「スマート」なコーディングを行う代わりに実際に標準関数を使用していることを意識して、プログラムが遭遇するすべてのエンコーディングを知っていると考えます...
DevSolar

6
1970年代からEBCDICをサポートするように作成されていた場合、isalphaとisupperはANSIでしたか、それとも当時の大半のコンパイラでサポートされていましたか?
nickalh

54

EBCDICとASCIIの両方をカバーしようとしているように見えます。代替方法はEBCDICでは機能しません(誤検出はありますが、誤検出はありません)。

CおよびC ++はないことを要求し'0'-'9'連続しています。

標準ライブラリ呼び出し、ASCII、EBCDIC、または他のシステムで実行されるかどうかを認識しているため、移植性が高く、おそらくより効率的です。


5
std::isupper現在インストールされているグローバルCロケールを実際に照会します。
Lingxi、

1
はい、そうです。このメソッドは、両方のエンコーディングをカバーするために作成されています。答えてくれてありがとう!
Vladimir Ch。

4
@Lingxi:真ですが、ロケールをASCIIからEBCDICに切り替えることができるという意味ではありません。ロケールに関係なく'A'残っている必要があり'A'ます。ASCIIからUTF-8への変換は可能です。
MSalters

2
@Lingxi:std::isupper現在インストールされているグローバルCロケールに対してクエリを実行します。ただし、文字リテラルを解釈するコンパイルのフェーズでは実行されません。
オービットのライトネスレース

1
@Lingxi-簡単なメモ。std::isupperほとんどの場合、本当に必要かどうかは疑問です。ユーザーからの入力に使用されるロケールを尊重します。しかし、ファイルを解析するとき、データベースと対話するときは、通常、他のロケールが想定されます。さらに、少なくともLinuxでは、これらのロケール関連の呼び出しは非常に遅くなります。たとえばstd::isalpha、単一の文字を実際に比較する前に、適切なロケール実装を「見つける」ために、dynamic_castを2回呼び出します。
ibre5041
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.