今回はソースコードから見ていくことにしましょう。
if ('A' <= ch && ch <= 'Z')
{
putchar(ch - 'A' + 'a');
}
やろうとしていることは簡単です。標準入力から 1 文字読み込み、アルファベットの大文字であれば小文字に変換して標準出力に書き込んでいます。
ここで、アルファベットの大文字かどうかの判別には isupper を使うべきだと主張する方がおられるかもしれませんが、その主張は必ずしも正しくありません。なぜなら、isupper の挙動はその時点で設定されているロケールに依存するからです。確実に、
というわけで、isupper ではなく、自前で判定を行っていること自体は間違いではないわけですが、問題はその判定方法にあります。ASCII や ASCII と(ほぼ)互換性のある文字コードの場合、多バイト文字さえ考慮しなければ上のコードでも問題ありません。しかし、このコードには少なくとも移植性がありません。標準 C/C++ の規格では、アルファベットの文字コードが連続していることが保証されていないからです。
アルファベットの文字コードが連続していない典型的な実例は EBCDIC です。メインフレーム等で使用される文字コードですが、文字コードの配置を見ると、'A'~'I', 'J'~'R', 'S'~'Z' の 3 つに分かれてしまっています。これでは、'A' <= ch && ch <= 'Z' の条件式ではアルファベットの大文字以外に対しても真になってしまいます。
なお、本来の EBCDIC ではアルファベットの小文字を扱うことができませんが、通常、小文字を扱えるように拡張が行われています。アルファベットの小文字は基本実行文字集合ですので、C/C++ の規格合致処理系では使えることを保証しなければなりません。幸いにして、EBCDIC の小文字を扱うための拡張では、大文字の文字コードから 0x40 を引けば小文字になります。しかし、大文字から一定の値を引けば対応する小文字になるかどうかも、C/C++ の規格上は保証されていないのです。
一方で、数字、すなわち '0'~'9' の文字コードが連続していることは、C/C++ の規格で保証されています。そのため、アルファベットに比べれば、数字はずっと扱いやすいのです。
現実の問題として、ASCII 系の文字コードを用いる処理系と、EBCDIC 等の非 ASCII 系の文字コードを用いる処理系の間で、移植性が要求されるケースは非常に稀です。ですから、アルファベットの連続性が必ずしも保証されないことを理解しておくことは重要ですが、実際のコーディングでは、対象とする処理系が ASCII 系の文字コードであると仮定できるのであれば、その旨を明記した上で、アルファベットの連続性を期待しても差し支えないでしょう。
トラックバック
ブックナビゲーション
- 技術情報
- Boost C++ Libraries メモ
- C++と組込み環境
- C++サンプル集
- C++テンプレート集
- C++プログラマのためのC言語入門
- C/C++迷信集
- [迷信] 'A'~'Z' の値は連続している
- [迷信] 0xe-0xe はゼロ
- [迷信] 1 バイトは 8 ビット
- [迷信] 2の累乗による割り算と右シフトは等価
- [迷信] FILE 型は構造体
- [迷信] abs は常に非負の値を返す
- [迷信] argv[0] はプログラム名
- [迷信] char 型は符号付き
- [迷信] double の出力書式は "%lf"
- [迷信] fflush で入力バッファをクリア
- [迷信] free でメモリを開放する
- [迷信] free に NULL を渡すとクラッシュする
- [迷信] gets は単純に fgets に置き換えられる
- [迷信] isalpha 関数の引数は char 型
- [迷信] new に失敗すると NULL が返る。
- [迷信] scanf ではバッファオーバーランを防げない
- [迷信] scanf でキーボードから入力
- [迷信] setjmp マクロの返却値は変数に代入できる
- [迷信] sizeof は定数式
- [迷信] void main(void)
- [迷信] とりあえず memset で初期化
- [迷信] アルゴリズム関数内で関数オブジェクトはコピーされない
- [迷信] オブジェクトの動的生成に失敗するとメモリリークする
- [迷信] コンストラクタから例外を送出してはならない
- [迷信] コンストラクタで自身をゼロクリア
- [迷信] コンパイラはプログラマの心を察してくれる
- [迷信] コンパイルエラーが出るのでアクセス指定子を修正
- [迷信] ソースコード中の即値を全廃せよ
- [迷信] ソースファイルの末尾に }
- [迷信] データ列のソートには qsort 関数を使うべし
- [迷信] プログラムは必ず main から始まる
- [迷信] 一重引用符の中には一文字しか書けない
- [迷信] 今どき int が 16 ビットの処理系なんて無い
- [迷信] 入力データ格納用配列のサイズは BUFSIZ
- [迷信] 割付けたメモリはプログラマが自分で解放しなければならない
- [迷信] 実数型とは浮動小数点型のことである
- [迷信] 引用符で囲んだヘッダ名はカレントディレクトリから探索する
- [迷信] 文字列から整数への変換には atoi
- [迷信] 構造体のタグ名は下線で始める
- [迷信] 構造体はクラスではない
- [迷信] 識別子に使える文字は英数字と下線のみ
- [迷信] 非局所オブジェクトは外部結合
- C言語再入門
- C言語徹底入門
- Drupal メモ
- TOPPERS 情報
- ライブラリ開発入門
- 分割コンパイルをきわめる
- 擬似プロセッサを作る
- 車輪の再発明
- 過去の情報

