今回も地味なライブラリ要素ですが、ロケールを制御するための<locale.h>です。ロケールは、標準Cライブラリのいろいろなところで顔を出しますので、先に片付けてしまうことにします。ただし、今回は"C"ロケールのみを対象とし、それ以外については拡張の余地を残すだけにしておきます。
ライブラリが"C"ロケールしか扱わないことを明示的に宣言するために、__ONLY_C_LOCALEというマクロを規定し、これが定義されている場合は、"C"ロケール以外は考慮しないことにします。このマクロが定義されていなくければ、とりあえずは"C"ロケールしか使えませんが、他のロケールのことも考慮することにします。
まず、<locale.h>でもNULLマクロを定義する必要がありますが、内容は<stddef.h>のものと同じですので、そちらを参照してください。次に、LC_〜で始まるロケールのカテゴリを表すマクロですが、整数定数式であればよいので、適当に連番を振ります。
#define LC_ALL 0 #define LC_COLLATE 1 #define LC_CTYPE 2 #define LC_MONETARY 3 #define LC_NUMERIC 4 #define LC_TIME 5
そして、lconv構造体を宣言します。
struct lconv { char *decimal_point; char *thousands_sep; char *grouping; char *int_curr_symbol; char *currency_symbol; char *mon_decimal_point; char *mon_thousands_sep; char *mon_grouping; char *positive_sign; char *negative_sign; char int_frac_digits; char frac_digits; char p_cs_precedes; char p_sep_by_space; char n_cs_precedes; char n_sep_by_space; char p_sign_posn; char n_sign_posn; };
最後は、localeconvおよびsetlocaleの関数原型です。
#ifdef __cplusplus extern "C" { #endif
struct lconv *localeconv(void); char *setlocale(int, const char*);
#ifdef __cplusplus } #endif
関数原型は、今回始めて登場しましたので、簡単に書き方について解説します。普段からC言語を使われている方にとっては、今さら関数原型の書き方なんかと思われるかもしれませんが、標準ライブラリの場合には、少しだけコツがあります。
というのは、上記を見ていただければお分かりのように、関数原型では仮引数名を記述していません。これは、仮引数に一般識別子を使うと、ユーザーが同名のマクロを定義した際に問題が生じるからです。予約済み識別子以外はユーザーに開放しなければなりませんので、敢えて仮引数名を省略しています。
インライン関数のように、どうしても仮引数名が必要な場合には、仮引数名は予約済み識別子を使用しなければなりません。同様に、インライン関数の内部で使用する自動変数やラベル名等も、すべて予約済み識別子でなければなりません。
長くなるので、今回はヘッダの記述だけの解説だけにしておきます。それぞれの関数の実装は次回以降にお話します。
▽続きを読む▽
ところで、<locale.h>も<stddef.h>と同様、C++では、ヘッダ内で宣言・定義する識別子はstd名前空間に入れなければ成りません。したがって、いったん<clocale>を記述し、<locale.h>から<clocale>をインクルードして、各識別子をusing指令で大域的な前空間に導入することになります。
/* locale.h */ #include <clocale> using std::lconv; using std::localeconv; using std::setlocale;
|