1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【小ネタ】大文字と小文字の変換について

Last updated at Posted at 2024-03-06

一般的な実装

大文字と小文字を変換するコードを書くとするなら、以下のようにするのが一般的だと思われます。

char toUpper(char c) {
    return ('a' <= c && c <= 'z') ? ('A' + c - 'a') : c;
}

char toLower(char c) {
    return ('A' <= c && c <= 'Z') ? ('a' + c - 'A') : c;
}
修正前のコード

(2024/03/07修正) 「diff を用いるのはややこしいのではないか」というご意見をいただき、以下のコードから修正しました。

char toUpper(char c) {
    auto diff = c - 'a';
    return (0 <= diff && diff <= ('z' - 'a')) ? ('A' + diff) : c;
}

char toLower(char c) {
    auto diff = c - 'A';
    return (0 <= diff && diff <= ('Z' - 'A')) ? ('a' + diff) : c;
}

ビット演算を用いた変換

手元の環境で実行してみればわかりますが、これで本当に動きます。
ロマンあふれるコードですね。

using byte = unsigned char;

char toUpper(char c) {
    char upper = c & ~0x20;
    return ('A' <= upper && upper <= 'Z') ? upper : c;
}

char toLower(char c) {
    char lower = c | 0x20;
    return ('a' <= lower && lower <= 'z') ? lower : c;
}

このコードについての説明は以下に記載します。

修正前のコード

(2024/03/07修正) return部分の比較演算を、以下から修正しました。

using byte = unsigned char;

char toUpper(char c) {
    char upper = c & ~0x20;
    return ((byte)(upper - 'A') <= (byte)('Z' - 'A')) ? upper : c;
}

char toLower(char c) {
    char lower = c | 0x20;
    return ((byte)(lower - 'a') <= (byte)('z' - 'a')) ? lower : c;
}

簡単な解説

A~Z と a~z のASCIIコードをビットに直して見比べてみるとよく分かります。

文字 大文字 小文字
A/a 0100_0001 0110_0001
B/b 0100_0010 0110_0010
C/c 0100_0011 0110_0011
... ... ...
Y/y 0101_1001 0111_1001
Z/z 0101_1010 0111_1010

大文字と小文字は, 0x20 でビットが立っている位置以外のビットは一致しているので、これを用いることで、大文字と小文字の変換を上のように記述することができます。

補足

(2024/03/07追記) このセクションの内容は本記事の主題から大きく逸れていたのと、C++ではこの方法には意味がないことが判明したため、修正しました。

修正前の内容

上のコードで、returnの部分にかかれているこの条件式について説明します。

(unsigned char)(lower - 'a') <= (unsigned char)('z' - 'a')

これは以下の条件式と同等です。

0 <= (lower - 'a') && (lower - 'a') <= ('z' - 'a')

詳しい説明は、以下の記事が分かりやすいです。

https://qiita.com/Tokeiya/items/1ee03c3a0648e79439b2

おわりに

ビット演算による実装は実際に様々なところで用いられており、.NET API の実装 でも見られます。

実際には元から用意されている関数を用いることが多いと思われますし、ここで紹介した方法ではàとÀの相互変換などには対応できません。

以上、小ネタでした。

1
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?