C言語とC++のlocale

localeの基本

日付の表示方法は国によって違う。アメリカなら’Friday, July 23, 2021’みたいになり、日本なら’2021/7/23’みたいになる。ほかにも、数字のカンマやピリオドのつけ方や金額表示の仕方もちがう。このような違いを扱うのがlocaleという概念。

catergoryには時刻を扱う。LC_TIMEなどいろいろあるが、ここでは一括で扱うLC_ALLを基本的に考える。

locale文字列は国・地域・言語を表す文字列で、”en-US”などと指定するがプログラム開始時には”C”になっており、”C”は1文字1charであることを意味している。”en-US”などの場合は言語と地域を表しており、さらに追加して”en-US.UTF8″などとも書ける。localeにNULLを渡すと現在の値を取得する。localeに空文字を渡すとユーザのデフォルトの国や地域そしてコードページが指定される。

これを英語のWindowsで実行すると以下のように出力される。

Englishが言語で、United Statesが国・地域、1252がコードページを表しこれは’en-US.1252″と同じ意味だろう。

localeに”.UTF8″とするとコードページだけ変えることができる。ここで指定したコードページはmbtowcsなどでワイド文字列に変換するときに使われる。

C++の場合

上記の話はC言語の話だった。C言語ではlocaleは1つしかなく、グローバル設定があるだけだったが、C++ではlocaleはクラスになった。

C言語との関係

stdにもstd::setlocale()があり、これは上記と同じようにグローバルなlocaleを設定するものだろう。

localeクラス

  • C++ではcategoryの代わりにFacetと言うようになった。
  • C言語ではsetlocal()で設定した情報はグローバルでどこかに格納されそれがアプリコードからは見えないところで参照されるが、C++のストリームでは明示的にlocaleクラスを設定しなければならない

コンストラクタ―

引数のないコンストラクタstd::locale()は、グローバルlocaleクラスのコピーを作成する。

文字列を指定

std::locale("ja-JP")は”ja-JP”のlocaleクラスを作成する。作成しただけではどこにも反映されない。

std::locale::classic();

これはsetlocal(LC_ALL, "C")と同じlocaleのインスタンス参照をかえす。

グローバルに設定

staticなstd::locale::global(locale& l)を呼ぶと、locale lをグローバルに設定する。

ストリームに設定

C++方式でグローバルに設定したlocaleはC言語の関数には影響を与えるがストリームには影響しない。ストリームに反映させるにはimbue()を使って設定する。

Facetとstd::codecvt

省略、facetはbasic_stringのtraitsのように自分で作ることができる、codecvtもfacetの一つ、これは非推奨でなおかつlocaleを使いにくい。globalなlocaleも反映されない。

Leave a Reply

Your email address will not be published. Required fields are marked *

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)