• R/O
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

マルチバイト・ワイド文字の処理


Commit MetaInfo

Revision1 (tree)
Time2017-08-16 13:10:45
Authortamiya25

Log Message

文字列処理

Change Summary

Incremental Difference

--- trunk/chproc/Makefile (nonexistent)
+++ trunk/chproc/Makefile (revision 1)
@@ -0,0 +1,21 @@
1+all: libchproc.a example
2+
3+libchproc.a: mbslen.o converter.o
4+ ar rcs libchproc.a \
5+ mbslen.o \
6+ converter.o
7+
8+mbslen.o: mbslen.c
9+ gcc -c mbslen.c
10+
11+converter.o: converter.c
12+ gcc -c converter.c
13+
14+example: example.c libchproc.a
15+ gcc -oexample example.c libchproc.a
16+
17+clean:
18+ rm -f *.o
19+ rm -f libchproc.a
20+ rm -f example
21+
--- trunk/chproc/README (nonexistent)
+++ trunk/chproc/README (revision 1)
@@ -0,0 +1,13 @@
1+文字列処理のプログラムコードです。
2+
3+make すると、静的ライブラリ libchproc.a と
4+例題プログラム (example) がビルドされます。
5+生成物をクリーンアップするには、make clean
6+してください。
7+
8+* ファイル
9+chproc.h -- ライブラリのためのヘッダファイル
10+mbslen.c -- マルチバイト文字列の文字数を調べる関数 mbslen()
11+converter.c -- マルチバイト、ワイド文字列を相互に変換
12+example.c -- 関数の使用例
13+
--- trunk/chproc/chproc.h (nonexistent)
+++ trunk/chproc/chproc.h (revision 1)
@@ -0,0 +1,12 @@
1+#ifndef _CHP_H
2+#define _CHP_H
3+
4+#include <wchar.h>
5+
6+int mbslen(const char *s, size_t *len_r);
7+
8+char* to_mbs(const wchar_t *s);
9+wchar_t* to_wcs(const char *s);
10+
11+#endif /* _CHP_H */
12+
--- trunk/chproc/converter.c (nonexistent)
+++ trunk/chproc/converter.c (revision 1)
@@ -0,0 +1,114 @@
1+/* converter.c
2+ *
3+ * ワイド文字列をマルチバイト文字列へ、またその逆に、
4+ * 文字列を変換する。
5+ *
6+ * マルチバイト、ワイド文字列を相互に変換する際、
7+ * 固定サイズの配列を使わず、必要バイト数を計算し
8+ * 動的にメモリを割り当てて変換を行う。
9+ *
10+ * 変換された文字列は、malloc() で動的に確保している
11+ * ので、使用後は free() で解放する必要がある。
12+ */
13+
14+#include <stdio.h>
15+#include <stdlib.h>
16+#include <string.h>
17+#include <stdint.h>
18+#include <wchar.h>
19+
20+/* to_mbs() -- ワイド文字列をマルチバイト文字列へ変換する
21+ *
22+ * 引数 s をマルチバイト文字列へ変換した文字列を返す。
23+ * 何らかのエラーが発生した場合は NULL を返す。
24+ * 返された文字列を使い終わったら free() で解放すること。
25+ *
26+ * この関数は wcstombs() を使い動的にメモリを割り当てた
27+ * 文字列を生成する例である。
28+ */
29+char* to_mbs(const wchar_t *s)
30+{
31+ size_t bytes;
32+ char *str;
33+
34+ // 引数チェック
35+ if (s == NULL)
36+ return NULL;
37+
38+ // wcstombs() の第1引数を NULL にすると、
39+ // マルチバイト文字での長さを返す。
40+ if ((bytes = wcstombs(NULL, s, 0)) == (size_t)-1)
41+ return NULL;
42+
43+ // 文字長に NUL 文字分の長さを加える
44+ // (桁溢れしたらエラーで終了)
45+ if ((bytes += 1) < 1)
46+ return NULL;
47+
48+ // メモリ確保
49+ if ((str = malloc(bytes)) == NULL)
50+ return NULL;
51+ memset(str, 0, bytes);
52+
53+ // 確保したメモリ領域に文字列の変換結果を
54+ // 格納する
55+ if (wcstombs(str, s, bytes) == (size_t)-1) {
56+ free(str);
57+ return NULL;
58+ }
59+
60+ return str;
61+}
62+
63+/* to_wcs() -- マルチバイト文字列をワイド文字列へ変換する
64+ *
65+ * 引数 s をワイド文字列へ変換した文字列を返す。
66+ * 何らかのエラーが発生した場合は NULL を返す。
67+ * 返された文字列を使い終わったら free() で解放すること。
68+ *
69+ * この関数は mbstowcs() を使い動的にメモリを割り当てた
70+ * ワイド文字列を生成する例である。
71+ */
72+wchar_t* to_wcs(const char *s)
73+{
74+ size_t len, bytes;
75+ wchar_t *str;
76+
77+ // 引数チェック
78+ if (s == NULL)
79+ return NULL;
80+
81+ // mbstowcs() の第1引数を NULL にすると
82+ // ワイド文字での文字数を返す
83+ if ((len = mbstowcs(NULL, s, 0)) == (size_t)-1)
84+ return NULL;
85+
86+ // 文字数に NUL 文字分の長さを加える
87+ // (桁溢れしたらエラーで終了)
88+ if ((len += 1) < 1)
89+ return NULL;
90+
91+ // 文字数に、1文字のサイズを掛け算して、
92+ // 必要バイト数を計算する。
93+ // ただし、桁溢れ防止のために、
94+ // 表現できる最大文字数に制限する。
95+ // (最大文字数を超えていたらエラーで終了)
96+ if (len > (SIZE_MAX / sizeof(wchar_t)))
97+ return NULL;
98+ bytes = sizeof(wchar_t) * len;
99+
100+ // メモリ確保
101+ if ((str = malloc(bytes)) == NULL)
102+ return NULL;
103+ memset(str, 0, bytes);
104+
105+ // 確保したメモリ領域に文字列の変換結果を
106+ // 格納する
107+ if (mbstowcs(str, s, len) == (size_t)-1) {
108+ free(str);
109+ return NULL;
110+ }
111+
112+ return str;
113+}
114+
--- trunk/chproc/example.c (nonexistent)
+++ trunk/chproc/example.c (revision 1)
@@ -0,0 +1,60 @@
1+/* example.c
2+ *
3+ * 文字処理の例。
4+ */
5+
6+#include <stdio.h>
7+#include <stdlib.h>
8+#include <string.h>
9+#include <wchar.h>
10+#include <locale.h>
11+#include "chproc.h"
12+
13+int main()
14+{
15+ char *mbs = "朝から晩まで、Internet";
16+ char *mbs2;
17+ wchar_t *ws;
18+ wchar_t *ws2 = L"明け方まで、MMORPG";
19+ size_t len;
20+
21+ // 初期化処理として、ロケールを設定する必要がある。
22+ if (setlocale(LC_ALL, "") == NULL) {
23+ fprintf(stderr, "setlocale() failed.\n");
24+ exit(1);
25+ }
26+
27+ // マルチバイト文字列の文字数を調べる
28+ if (mbslen(mbs, &len)) {
29+ fprintf(stderr, "mbslen() failed.\n");
30+ exit(1);
31+ }
32+ printf("%u\n\n", len);
33+
34+ // ワイド文字列に変換する
35+ if ((ws = to_wcs(mbs)) == NULL) {
36+ fprintf(stderr, "to_wcs() failed.\n");
37+ exit(1);
38+ }
39+
40+ // ワイド文字列の出力は、%s ではなく %S なので注意!
41+ printf("%S\n\n", ws);
42+
43+ // メモリ解放
44+ free(ws);
45+
46+ // 今度は、ワイド文字列をマルチバイト文字列にする
47+ if ((mbs2 = to_mbs(ws2)) == NULL) {
48+ fprintf(stderr, "to_mbs() failed.\n");
49+ exit(1);
50+ }
51+ if (mbslen(mbs2, &len)) {
52+ fprintf(stderr, "mbslen() failed.\n");
53+ exit(1);
54+ }
55+ printf("%u\n\n%s\n", len, mbs2);
56+ free(mbs2);
57+
58+ return 0;
59+}
60+
--- trunk/chproc/mbslen.c (nonexistent)
+++ trunk/chproc/mbslen.c (revision 1)
@@ -0,0 +1,56 @@
1+/* mbslen.c
2+ *
3+ * 関数 mbslen() を作る。
4+ * mbslen() はマルチバイト文字列の文字数を返す。
5+ * strlen() とは異なり文字列の「バイト数」ではなく、
6+ * 「文字数」である。
7+ */
8+
9+#include <stdio.h>
10+#include <stdlib.h>
11+#include <string.h>
12+#include <wchar.h>
13+
14+/* mbslen() -- マルチバイト文字列の文字数を返す
15+ *
16+ * s で指定された文字列の文字数を len_r で示される
17+ * 場所に格納する。 この関数の返り値は、成功ならば
18+ * 0 を、エラーならば 0 以外を返す。
19+ *
20+ * この関数は mbrlen() で文字数を調べる例である。
21+ */
22+int mbslen(const char *s, size_t *len_r)
23+{
24+ size_t r;
25+ size_t n = 0; // 文字数
26+ size_t m = 0; // 調べ終わった合計バイト数
27+ mbstate_t state;
28+
29+ // 引数チェック
30+ if (s == NULL)
31+ return 1; // error
32+
33+ // 状態初期化
34+ memset(&state, 0, sizeof(mbstate_t));
35+
36+ // mbrlen() で文字数を調べる
37+ while (r = mbrlen(&s[m], MB_CUR_MAX, &state)) {
38+
39+ // mbrln() の返り値がエラーかどうかチェック
40+ if (r == (size_t)-1 || r == (size_t)-2)
41+ return 1; // error
42+
43+ // 合計バイト数に加算
44+ m += r;
45+
46+ // 合計文字数を増やす
47+ n++;
48+ }
49+
50+ // 結果を返す
51+ if (len_r != NULL)
52+ *len_r = n;
53+
54+ return 0; // 正常終了
55+}
56+