[C][SJIS] Shift_JIS 文字関係のユーティリティ ================================================================================ Shift_JIS 文字関係のユーティリティとして、次のようなものを作った。 ただし、リトル・エンディアン限定。 関数の概要 --- int stoi(const char* s); 日本語の数字列を数値(int)に変換する。 int sjisToDigit(const char* s); 日本語の数字を数値(int)に変換する。 int isSjisDigit(const char* s); 数字("0"~"9")か判断する。 int isSjisHiragana(const char* s); ひらがなか判断する。 int isSjisKatakana(const char* s); カタカナか判断する。 --- 関数の詳細 --- int stoi(const char* s); 引数sで与えられた Shift_JIS で書かれた日本語の数字列を数値(int)に変換する。 この関数は、標準関数 atoi() の Shift_JIS 版であるが、負値を扱えない。 数字列は Shift_JIS の数字以外は記述できない。Shift_JIS の数字以外が出てきた 時点で変換をやめる。 引数 s Shift_JIS で書かれた日本語の数字列 戻り値 Shift_JIS で書かれた日本語の数字列を変換した数値 int sjisToDigit(const char* s); 引数sで与えられた Shift_JIS で書かれた日本語の数字を数値(int)に変換する。 この数字は、C 言語の文字列の要件を満たす必要はなく、引数 s からの 2 バイトだ けで判断する。 引数 s Shift_JIS で書かれた日本語の数字 戻り値 Shift_JIS で書かれた日本語の数字を変換した数値。変換できない場合は -1 int isSjisDigit(const char* s); 引数sで与えられた Shift_JIS で書かれた日本語が数字("0"~"9")か判断する。 この数字は、C 言語の文字列の要件を満たす必要はなく、引数 s からの 2 バイトだ けで判断する。 Shift_JIS の"0"~"9"は、0x824f ~ 0x8258. 引数 s Shift_JIS で書かれた日本語の数字 戻り値 数値であれば 1.そうでなければ 0 int isSjisHiragana(const char* s); 引数sで与えられた Shift_JIS で書かれた日本語がひらがなか判断する。 この数字は、C 言語の文字列の要件を満たす必要はなく、引数 s からの 2 バイトだ けで判断する。 Shift_JIS のひらがなは、0x829F ~ 0x82F1. 引数 s Shift_JIS で書かれた日本語文字列 戻り値 ひらがなであれば 1.そうでなければ 0 int isSjisKatakana(const char* s); 引数 s で与えられた Shift_JIS で書かれた日本語がカタカナか判断する。 この数字は、C言語の文字列の要件を満たす必要はなく、引数 s からの 2 バイトだ けで判断する。 Shift_JIS のカタカナは、0x829F ~ 0x82F1. 引数 s Shift_JIS で書かれた日本語文字列 戻り値 カタカナであれば 1.そうでなければ 0 --- ▲ 公開用ヘッダー □ sjisUtil.h --- /* ============================================================================ Name : sjisUtil.h Author : marunomaruno Version : V1.0, 2012-06-08 Copyright : marunomaruno Description : リトルエンエンディアンの Shift_JIS 関係のユーティリティ(公開用) ============================================================================ */ #ifndef SJIS_UTIL_H_ #define SJIS_UTIL_H_ /** * 引数 s で与えられた Shift_JIS で書かれた日本語がひらがなか判断する。 * この数字は、C言語の文字列の要件を満たす必要はなく、引数 s からの 2 バイトだけで判断する。 * Shift_JIS のひらがなは、0x829F ~ 0x82F1. * @param s Shift_JIS で書かれた日本語文字列 * @return ひらがなであれば 1.そうでなければ 0 */ int isSjisHiragana(const char* s); /** * 引数 s で与えられた Shift_JIS で書かれた日本語がカタカナか判断する。 * この数字は、C 言語の文字列の要件を満たす必要はなく、引数 s からの 2 バイトだけで判断する。 * Shift_JIS のカタカナは、0x829F ~ 0x82F1. * @param s Shift_JIS で書かれた日本語文字列 * @return カタカナであれば 1.そうでなければ 0 */ int isSjisKatakana(const char* s); /** * 引数 s で与えられた Shift_JIS で書かれた日本語の数字列を数値(int)に変換する。 * この関数は、標準関数 atoi() の Shift_JIS 版であるが、負値を扱えない。 * 数字列は Shift_JIS の数字以外は記述できない。 Shift_JIS の数字以外が出てきた時点で変換をやめる。 * @param s Shift_JIS で書かれた日本語の数字列 * @return Shift_JIS で書かれた日本語の数字列を変換した数値 */ int stoi(const char* s); /** * 引数 s で与えられた Shift_JIS で書かれた日本語の数字を数値(int)に変換する。 * この数字は、C 言語の文字列の要件を満たす必要はなく、引数 s からの 2 バイトだけで判断する。 * @param s Shift_JIS で書かれた日本語の数字 * @return Shift_JIS で書かれた日本語の数字を変換した数値。変換できない場合は-1 */ int sjisToDigit(const char* s); /** * 引数 s で与えられた Shift_JIS で書かれた日本語が数字("0"~"9")か判断する。 * この数字は、C 言語の文字列の要件を満たす必要はなく、引数 s からの 2 バイトだけで判断する。 * Shift_JIS の"0"~"9"は、0x824f ~ 0x8258. * @param s Shift_JIS で書かれた日本語の数字 * @return 数値であれば 1.そうでなければ 0 */ int isSjisDigit(const char* s); #endif /* SJIS_UTIL_H_ */ ---- ▲ 非公開用ヘッダー 内部的に使うだけの関数の定義。 リトルエンディアンを意識するのはここだけ。 □ sjisUtilInner.h --- /* ============================================================================ Name : sjisUtilInner.h Author : marunomaruno Version : V1.0, 2012-06-08 Copyright : marunomaruno Description : リトルエンエンディアンの Shift_JIS 関係のユーティリティ(内部用) ============================================================================ */ #ifndef SJIS_UTIL_INNER_H_ #define SJIS_UTIL_INNER_H_ /** * 2 バイト文字 s が 2 バイト文字 start と end の間に入っているか判断する。 * この 2 バイト文字は、C 言語の文字列の要件を満たす必要はなく、それぞれの引数からの 2 バイトだけで判断する。 * @param s Shift_JIS で書かれた 2 バイト文字 * @param start Shift_JIS で書かれた 2 バイト文字で、検査する範囲の始端 * @param end Shift_JIS で書かれた 2 バイト文字で、検査する範囲の終端 * @return 範囲内であれば 1.そうでなければ 0 */ static int inRange2byteChar(const char* s, const char* start, const char* end); #endif /* SJIS_UTIL_INNER_H_ */ --- ▲ モジュール □ sjisUtil.c --- /* ============================================================================ Name : sjisUtil.c Author : marunomaruno Version : V1.0, 2012-06-08 Copyright : marunomaruno Description : リトルエンエンディアンの Shift_JIS 関係のユーティリティ ============================================================================ */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "sjisUtil.h" #include "sjisUtilInner.h" /** * 引数 s で与えられた Shift_JIS で書かれた日本語の数字列を数値(int)に変換する。 * この関数は、標準関数 atoi() の Shift_JIS 版であるが、負値を扱えない。 * 数字列は Shift_JIS の数字以外は記述できない。 Shift_JIS の数字以外が出てきた時点で変換をやめる。 * @param s Shift_JIS で書かれた日本語の数字列 * @return Shift_JIS で書かれた日本語の数字列を変換した数値 */ int stoi(const char* s) { int num = 0; int i; for (i = 0; i < strlen(s); i += 2) { int digit = 0; if ((digit = sjisToDigit(&s[i])) == -1) { break; } num = num * 10 + digit; } return num; } /** * 引数 s で与えられた Shift_JIS で書かれた日本語の数字を数値(int)に変換する。 * この数字は、C 言語の文字列の要件を満たす必要はなく、引数 s からの 2 バイトだけで判断する。 * @param s Shift_JIS で書かれた日本語の数字 * @return Shift_JIS で書かれた日本語の数字を変換した数値。変換できない場合は -1 */ int sjisToDigit(const char* s) { if (!isSjisDigit(s)) { return -1; } return s[1] - 0x4f; } /** * 引数 s で与えられた Shift_JIS で書かれた日本語が数字("0"~"9")か判断する。 * この数字は、C 言語の文字列の要件を満たす必要はなく、引数 s からの 2 バイトだけで判断する。 * Shift_JIS の"0"~"9"は、0x824f ~ 0x8258. * @param s Shift_JIS で書かれた日本語の数字 * @return 数値であれば 1.そうでなければ 0 */ int isSjisDigit(const char* s) { return inRange2byteChar(s, "0", "9"); } /** * 引数 s で与えられた Shift_JIS で書かれた日本語がひらがなか判断する。 * この数字は、C 言語の文字列の要件を満たす必要はなく、引数 s からの 2 バイトだけで判断する。 * Shift_JIS のひらがなは、0x829F ~ 0x82F1. 長音(ー)もひらがなとする。 * @param s Shift_JIS で書かれた日本語文字列 * @return ひらがなであれば 1.そうでなければ 0 */ int isSjisHiragana(const char* s) { return inRange2byteChar(s, "ぁ", "ん") || inRange2byteChar(s, "ー", "ー"); } /** * 引数 s で与えられた Shift_JIS で書かれた日本語がカタカナか判断する。 * この数字は、C 言語の文字列の要件を満たす必要はなく、引数 s からの 2 バイトだけで判断する。 * Shift_JIS のカタカナは、0x829F ~ 0x82F1. 長音(ー)もカタカナとする。 * @param s Shift_JIS で書かれた日本語文字列 * @return カタカナであれば 1.そうでなければ 0 */ int isSjisKatakana(const char* s) { return inRange2byteChar(s, "ァ", "ヶ") || inRange2byteChar(s, "ー", "ー"); } /** * 2 バイト文字sが 2 バイト文字startとendの間に入っているか判断する。 * この 2 バイト文字は、C 言語の文字列の要件を満たす必要はなく、それぞれの引数からの 2 バイトだけで判断する。 * @param s Shift_JIS で書かれた 2 バイト文字 * @param start Shift_JIS で書かれた 2 バイト文字で、検査する範囲の始端 * @param end Shift_JIS で書かれた 2 バイト文字で、検査する範囲の終端 * @return 範囲内であれば 1.そうでなければ 0 */ int inRange2byteChar(const char* s, const char* start, const char* end) { typedef union { unsigned char str[2]; unsigned short num; } DoubleByteChar; DoubleByteChar value; DoubleByteChar startValue; DoubleByteChar endValue; value.str[0] = s[1]; value.str[1] = s[0]; startValue.str[0] = start[1]; startValue.str[1] = start[0]; endValue.str[0] = end[1]; endValue.str[1] = end[0]; return (startValue.num <= value.num) && (value.num <= endValue.num); } --- ▲ テスト 上記の関数を確認するためのテスト・プログラム。 数字、ひらがな、かたかなの限界値をチェックする。 また、リトルエンディアン前提なので、バイト順が逆転している場合に範囲になるかどう かもチェックする。 □ test.c --- /* ============================================================================ Name : test.c Author : marunomaruno Version : V1.0, 2012-06-08 Copyright : marunomaruno Description : リトルエンエンディアンの Shift_JIS 関係のユーティリティのテスト・ プログラム ============================================================================ */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include "sjisUtil.h" int main(void) { printf("test start\n"); char hiragana[][3] = { "あ", "い", "か", "さ", "た", "や", "ら", "わ", "っ", "ん", "ー", }; char katakana[][3] = { "ア", "イ", "ウ", "サ", "タ", "ヤ", "ラ", "ワ", "ッ", "ン", "ー", }; char num[][3] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", }; char other[][3] = { { 0x4e, 0x82, '0' }, { 0x59, 0x82, '0' }, { 0x9e, 0x82, '0' }, { 0xf2, 0x82, '0' }, { 0xfc, 0x82, '0' }, { 0x97, 0x823, '0' }, "氓", "A", "一", "所", }; int i; // 長音も含め、ひらがな、カタカナ、数字 for (i = 0; i < 11; i++) { assert(isSjisHiragana(hiragana[i])); } for (i = 0; i < 11; i++) { assert(isSjisKatakana(katakana[i])); } for (i = 0; i < 10; i++) { assert(isSjisDigit(num[i])); } // 長音 assert(isSjisKatakana("ー")); assert(isSjisHiragana("ー")); // ひらがな、カタカナ、数字でない for (i = 0; i < 10; i++) { assert(!isSjisHiragana(katakana[i])); assert(!isSjisHiragana(num[i])); assert(!isSjisHiragana(other[i])); } for (i = 0; i < 10; i++) { assert(!isSjisKatakana(hiragana[i])); assert(!isSjisKatakana(num[i])); assert(!isSjisKatakana(other[i])); } for (i = 0; i < 10; i++) { assert(!isSjisDigit(hiragana[i])); assert(!isSjisDigit(katakana[i])); assert(!isSjisDigit(other[i])); } // 全角数字を数値に変換 for (i = 0; i < 10; i++) { assert(i == sjisToDigit(num[i])); } // 全角数字を数値に変換 assert(1234 == stoi("1234")); assert(1234567890 == stoi("1234567890")); assert(0 == stoi("01234567890")); assert(123456 == stoi("12345607890")); // 文字列としての検査 char* s1; s1 = "あいうえおー"; for (i = 0; i < strlen(s1); i += 2) { if (!isSjisHiragana(&s1[i])) { assert(0); } } assert(1); s1 = "あいうえおー1"; for (i = 0; i < strlen(s1); i += 2) { if (!isSjisHiragana(&s1[i])) { assert(1); } } assert(i >= strlen(s1)); s1 = "あいうえおーア"; for (i = 0; i < strlen(s1); i += 2) { if (!isSjisHiragana(&s1[i])) { assert(1); } } assert(i >= strlen(s1)); s1 = "アイウエオー"; for (i = 0; i < strlen(s1); i += 2) { if (!isSjisKatakana(&s1[i])) { assert(0); } } assert(1); s1 = "アイウエオー1"; for (i = 0; i < strlen(s1); i += 2) { if (!isSjisKatakana(&s1[i])) { assert(1); } } assert(i >= strlen(s1)); s1 = "アイウエオーあいうえおア"; for (i = 0; i < strlen(s1); i += 2) { if (!isSjisKatakana(&s1[i])) { assert(1); } } assert(i >= strlen(s1)); printf("test end\n"); return EXIT_SUCCESS; } --- 以上
最新の画像[もっと見る]
- あけましておめでとうございます 11年前
- 今年もよろしくお願いいたします 12年前
- あけましておめでとうございます 13年前
- あけましておめでとうございます 16年前
※コメント投稿者のブログIDはブログ作成者のみに通知されます