C++で文字列を小文字に変換する方法

この記事では、C++で文字列を小文字に変換する方法を紹介します。

C++で文字列変換を行う前に最初に自問するのは、入力文字列のエンコーディングの種類です。マルチバイトのエンコーディング文字で std::lower を使用すると、バグのあるコードが確実に得られるためです。

以下の関数は std::string の小文字変換をきちんと実装しているように見えても、エンコーディングが UTF-8 であるため、すべての文字を小文字に変換しているわけではない。

#include <iostream>
#include <algorithm>

std::string toLower(std::string s) {
    std::transform(s.begin(), s.end(), s.begin(),
       [](unsigned char c){ return std::tolower(c); }
    );
    return s;
}

int main() {
    std::string string1 = u8"ÅSH to LoWer WÅN";
    std::cout << "input string:  " << string1 << std::endl
            << "output string: " << toLower(string1) << std::endl;
    return 0;
}

上記のコードは ASCII 文字列やその他の非 ASCII 文字列に対しては問題なく動作しますが、ラテン文字を含むような少し変わった入力を与えると、出力は満足のいくものではありません。

出力:

input string:  ÅSH to LoWer WÅN
output string: Åsh to lower wÅn

これは、Å 記号を å に下げるべきだったので、正しくありません。では、この問題を解決して正しい出力を得るにはどうすればよいのでしょうか?

この問題を解決する最良の移植性のある方法は、ICU (International Components for Unicode) ライブラリを使用することです。

ソースファイルには以下のヘッダを含めるだけです。これらのライブラリは、あなたのプラットフォームに既に含まれていて利用可能な可能性が高いので、コードサンプルは問題なく動作するはずです。しかし、IDE/コンパイル時のエラーが発生した場合は、ICU documentation website にあるライブラリのダウンロード方法を参照してください。

#include <unicode/unistr.h>
#include <unicode/ustream.h>
#include <unicode/locid.h>

これでヘッダが含まれるようになったので、以下のように std::string を小文字に変換するコードを書くことができるようになりました。

#include <iostream>
#include <unicode/unistr.h>
#include <unicode/ustream.h>
#include <unicode/locid.h>

int main() {
    std::string string1 = u8"ÅSH to LoWer WÅN";
    icu::UnicodeString unicodeString(string1.c_str());
    std::cout << "input string:  " << string1 << std::endl
              << "output string: " << unicodeString.toLower() << std::endl;
    return 0;
}

なお、このコードをコンパイルする際には、ICU ライブラリの依存関係を含めるために、以下のコンパイラフラグをつけてコンパイルする必要があります。

g++ sample_code.cpp -licuio -licuuc -o sample_code

コードを実行すると、期待通りの正しい出力が得られます。

input string:  ÅSH to LoWer WÅN
output string: åsh to lower wån

まったく同じ関数で、通常ユーザー入力として予期しないいくつかの異なる言語を処理できます。また、toLower 関数のパラメーターとしてロケールを明示的に指定することもできます。

#include <iostream>
#include <unicode/unistr.h>
#include <unicode/ustream.h>
#include <unicode/locid.h>

int main() {
    std::string string2 = "Κάδμῳ ἀπιϰόμενοι.. Ελληνας ϰαὶ δὴ ϰαὶ γράμματα, οὐϰ ἐόντα πρὶν Ελλησι";
    icu::UnicodeString unicodeString2(string2.c_str());
    std::cout  << unicodeString2.toLower("el_GR") << std::endl;
    return 0;
}

関連記事 - C++ String

  • C++で文字列を Char 配列に変換する方法
  • C++ でデリミタを使用して文字列を解析する方法
  • comments powered by Disqus