この章では、XPG において仕様が決定された国際化文字対応・分類プログラミングインタフェース、および Solaris で仕様が追加された日本語ロケール用文字対応・分類インタフェースを紹介し、日本語文字の分類について説明します。
XPG では、各ロケールの LC_CTYPE カテゴリに対して一定の文字クラスを定義し、アプリケーションプログラマが各文字を処理する際の分類 (大文字アルファベットかどうかなど) を支援しています。さらに XPG では、大文字・小文字の対応を定義する仕組みも LC_CTYPE の中で定義しているため、toupper() や tolower() などの API を通して簡単に大文字小文字の変換ができます。
このような XPG が規定する文字クラス分類・文字対応 API には、それぞれバイト単位処理・ワイド文字表現単位処理の両方が用意されています。
Solaris では日本語テキストで使用する文字 (漢字など) を同様の API で処理できるように、日本語ロケール専用の文字分類クラスおよび文字対応を追加しています。これらの文字対応と文字分類の処理は、各文字をワイド文字表現に変換して API を呼び出します。Solaris における JFP で提供された日本語ロケールの定義については『JFP ユーザーズガイド』の第 2 章の表 2-3「X/Open で規定された文字分類クラス名と日本語ロケールでの定義範囲」を参照してください。
文字対応の操作のための API のうち、日本語ロケールの文字集合の処理に有効な API を表 3-1、表 3-2 に示します。その他にも API が用意されています。詳しくはマニュアルページ (towctrans(3C)、wctrans(3C)、wctrans_ja(3C) など) を参照してください。
表 3-1 文字対応 API その 1|
XPG で規定されるインタフェース名 |
作用 |
|---|---|
|
towupper (wc) |
ワイド文字 wc に対応する大文字ワイド文字表現を返す。なければ wc をそのまま返す |
|
towlower (wc) |
ワイド文字 wc に対応する小文字ワイド文字表現を返す。なければ wc をそのまま返す |
|
towctrans (wc, wctrans("タグ名")) |
タグ名 に基づいてワイド文字 wc に対応したワイド文字表現を返す。なければ wc をそのまま返す |
|
wctrans ("タグ名") |
towctrans () で使う、タグ名に対応する値を返す。タグ名として以下が使用できる。 "tolower", "toupper" |
表 3-2 文字分類 API その 2
|
日本語 Solaris で拡張されたインタフェース名 |
作用 |
|---|---|
|
wctrans("タグ名") |
towctrans() で使う、タグ名に対応する値を返す。Solaris では日本語ロケールにおいて以下をタグ名として使用できる |
|
|
"tojhira" "tojkata" "tojisx0208" "tojisx0201" |
日本語文字対応の API を用いたプログラム例を 2 つ紹介します。使用する場合には wchar.h、wctype.h ヘッダファイルを取り込むこと、また setlocale() を処理の最初の段階で呼び出して動作ロケールを適切に設定することが必要です。
例 3-1 では、入力ファイル中に存在する JIS X 0201 かな文字 (半角カナ) を JIS X 0208 かな文字に変換するフィルタを紹介します。既存のアプリケーション・ネットワークの中には、規約上、または実装上の制限により JIS X 0201 かな文字を使用したデータ通信ができないものがあります。そのような環境に対しては通信に先立ち、JIS X 0201 かな文字を JIS X 0208 かな文字に変換するなど入力ファイルの加工が必要です。この例では、入力ファイルを 1 行ずつワイド文字列として読み込み、各ワイド文字を towctrans() で変換しています。
sun% cat my_kanato208.c
/*
* Read lines from a file and convert JIS X 0201 kana
* characters to the correspondent ones in JIS X 0208
* set. This will stop processing if the input file
* reaches EOF. It is assumed that each line has
* at most BUFSIZ -1 wide char length.
*
* Actual processing is done by my_kanato208(), which
* does the followings.
* 1. Get the length of wide string.
* 2. Convert each wide char from the top
* of the string by applying towctrans().
* (The return value of towctrans() will be
* the same if there's no correspondent char.)
* 3. Write the correspondent wide char to
* original string.
*/
#include <stdio.h>
#include <locale.h>
#include <wchar.h>
#include <wctype.h>
static void my_kanato208(wchar_t *);
int
main(int argc, char *argv[])
{
wchar_t buf[BUFSIZ];
setlocale(LC_ALL, "");
while (fgetws(buf, BUFSIZ, stdin) != (wchar_t *)NULL) {
my_kanato208(buf);
fprintf(stdout, "%S",buf);
}
return (0);
}
static void
my_kanato208(wchar_t *wcp)
{
size_t wstr_len;
wint_t retval;
int index;
wstr_len = wcslen(wcp);
for (index = 0; index < wstr_len; index++) {
retval = towctrans((wint_t)wcp[index],
wctrans("tojisx0208"));
wcp[index] = retval;
}
}
sun% cat file3
新しいシステム*は現在のネットワーク環境を変えることなく
インターネット*とのシームレス*な接続を可能にします。また
セキュリティ*の問題も新しい認証テクノロジー*を用いることで
アドミニストレータ*の負担を減らしています。
sun% cc -o my_kanato208 my_kanato208.c
sun% cat file3 | ./my_kanato208
新しいシステム*は現在のネットワーク*環境を変えることなく
インターネット*とのシームレス*な接続を可能にします。また
セキュリティ*の問題も新しい認証テクノロジー*を用いることで
アドミニストレータ*の負担を減らしています。
* の部分のカタカナは、半角カタカナになります。
例 3-2 は wcstol() の拡張例です。現在の Solaris が提供する日本語ロケールでは、JIS X 0208 文字集合で表された数値文字列に対して、直接 wcstol() を呼び出すことができません。そこで、数値文字列をワイド文字列データとして読み込み、towctrans() で対応する JIS X 0201 文字に変換し、wcstol() を呼び出しています。
sun% cat my_wcstol.c
/*
* Read lines from a file and convert tokenized
* wide char string to long integer.
* Conversion will stop if the input file reaches
* EOF, and output the sum of input integers.
* It is assumed that each line has at most
* BUFSIZ - 1 wide char length.
*
* Actual conversion is done by my_wcstol(), which
* does the followings.
* 1. Get the length of wide char string.
* 2. Convert each wide char from the top
* of the string by applying towctrans().
* The correspondent JIS X 0201 wide char value
* will be gotten for each JIS X 0208 digit chars
* in the string.
* (The return value of towctrans() will be
* the same if there's no correspondent char.)
* 3. Write the correspondent wide char to
* original string.
* 4. Call wcstol() with the converted wide string.
*/
#include <stdio.h>
#include <locale.h>
#include <wchar.h>
#include <wtype.h>
#include <errno.h>
#define WRET L'¥n'
static long my_wcstol(wchar_t *, wchar_t **, int);
int
main(int argc, char *argv[])
{
wchar_t buf[BUFSIZ];
wchar_t *headp, *nextp;
long retval, total;
setlocale(LC_ALL, "");
total = retval = 0;
while (fgetws(buf, BUFSIZ, stdin) != (wchar_t *)NULL) {
headp = buf;
while (headp != (wchar_t *)NULL) {
errno = 0;
retval = my_wcstol(headp, 0);
if (errno != 0) {
if (nextp[0] == WRET) {
break;
} else {
perror("my_wcstol()");
exit (-1);
}
}
fprintf(stdout, "retval = [%ld]¥n", retval);
total += retval;
headp = nextp;
}
}
fprintf(stdout, "Total = %ld.¥n", total);
return (0);
}
static long
my_wcstol(wchar_t *wcp, wchar_t **endp, int base)
{
size_t wstr_len;
wint_t retval;
int index;
long ret_val;
wstr_len = wcslen(wcp);
for (index = 0; index < wstr_len; index++) {
retval = towctrans((wint_t)wcp[index], wctrans("tojisx0201"));
wcp[index] = (wchar_t)retval;
} ret_val = wcstol((const wchar_t *)wcp, endp, base);
return (ret_val);
}
sun% cat file4
343 34534 12
345345 345345
39857 398 5834589
sun% cc -o my_wcstol my_wcstol.c
sun% ./my_wcstol < file4
retval = [343]
retval = [34534]
retval = [12]
retval = [345345]
retval = [345345]
retval = [39857]
retval = [398]
retval = [5834589]
Total = 6600423.
文字分類の操作のための API のうち、日本語ロケールの文字集合の処理に有効な API を表 3-3、表 3-4 に示します。その他にも API が用意されています。詳しくはマニュアルページ (iswalpha(3C)、wctype(3C)、wctype_ja(3C)) などを参照してください。
表 3-3 文字分類 API その 1|
XPG で規定されるインタフェース名 |
作用 |
|---|---|
|
iswctype(wc, type) |
wc が type クラスに属するかどうか調べる |
|
wctype("タイプ名") |
iswctype() の第 2 引数を、タイプ名から作成する。 XPG で標準文字クラスとして 規定されているものは以下のとおり |
|
|
"alnum" "alpha" "cntrl" "digit""graph""lower" "print""punct""space""upper" "xdigit""blank" |
表 3-4 文字分類 API その 2
|
日本語 Solaris で拡張されたインタフェース名 |
作用 |
|---|---|
|
wctype("タイプ") |
iswctype() の第 2 引数を、タイプ名から作成する。Solaris で日本語ロケール向けに拡張された文字クラスは以下のとおり |
|
|
"jkanji"() "jkata"() "jhira"() "jdigit"() "jparen"() "jline"() "jisx0201r"() "jisx0208"()"jisx0212"() "udc"()"vdc"() "jalpha""jspecial" "jgreek""jrussian""junit" "jsci""jgen" "jpunct" |
日本語文字分類の API を用いたプログラム例を紹介します。前述の文字対応 API の場合と同様に、使用する場合には wchar.h ヘッダファイルを取り込むこと、また setlocale() を処理の最初の段階で呼び出して動作ロケールを適切に設定することが必要です。
例 3-3 では、入力ファイルをワイド文字列として読み込んで入力中の JIS X 0208 ひらがなとカタカナを交換し、JIS X 0208 数字文字は ASCII に変換して出力します。
sun% cat my_charconv.c
/*
* Read lines from a file and convert JIS X 0208 hiragana
* characters to JIS X 0208 katakana characters, and
* vice versa. In addition, JIS X 0208 digit characters
* are converted to the correspondent ones in JIS X 0201
* characters.
* Conversion will stop if the input file reaches EOF.
* It is assumed that each line has at most BUFSIZ - 1
* wide char length.
*
* Actual conversion is done by my_charconv(), which does
* the followings.
* 1. Get the length of the wide string.
* 2. Convert each wide char from the top
* of the string by applying towctrans().
* (The return value of towctrans() will be
* the same if there's no correspondent char.)
* 3. Write the correspondent wide char to
* original string and output it.
*/
#include <stdio.h>
#include <locale.h>
#include <wchar.h>
#include <wctype.h>
#include <jctype.h>
#include <errno.h>
#define WRET L'¥n'
static int my_charconv(wchar_t *);
int
main(int argc, char *argv[])
{
wchar_t buf[BUFSIZ];
wchar_t *headp, *nextp;
long retval, total;
setlocale(LC_ALL, "");
total = retval = 0;
while (fgetws(buf, BUFSIZ, stdin) != (wchar_t *)NULL) {
retval = my_charconv(buf);
if (retval == -1) {
perror("my_charconv()");
exit(-1);
}
fprintf(stdout, "%S", buf);
}
return (0);
}
static int
my_charconv(wchar_t *wcp)
{
size_t wstr_len;
wint_t retval;
int index;
long ret_val;
wstr_len = wcslen(wcp);
for (index = 0; index < wstr_len; index++) {
errno = 0;
if (iswctype((wint_t)wcp[index], wctype("jhira")))
retval = towctrans((wint_t)wcp[index], wctrans("tojkata"));
else if (iswctype((wint_t)wcp[index], wctype("jkata")))
retval = towctrans((wint_t)wcp[index], wctrans("tojhira"));
else if (iswctype((wint_t)wcp[index], wctype("jdigit")))
retval = towctrans((wint_t)wcp[index], wctrans("tojisx0201"));
else
retval = wcp[index];
if (errno != 0)
return (-1);
wcp[index] = (wchar_t)retval;
}
return (0);
}
sun% cat file5ひらがなはかたかなに置換されます。
カタカナハヒラガナニ置換サレマス。
漢字、記号、全角alphabetや
JIS X 0201 カナナドハ* 置換 サレマセン*。
sun% cc -o my_charconv my_charconv.c
sun% ./my_charconv < file5
ヒラガナハカタカナニ置換サレマス。
かたかなはひらがなに置換されます。
漢字、記号、全角alphabetヤ
JIS X 0201 カナナドハ* 置換 サレマセン*。
* の部分のカタカナは、半角カタカナになります。