半角カナ文字の検査、全角への変換ルーチン

文字を全角/半角カナ[濁音、半濁音]/英数字のいずれかに分類し、表示する例題です。この例では、半角カナを全て全角へと変換し、英数字は全て大文字に変換しています。

 半角カナ文字の検査、全角への変換ルーチン(list_63.c)
//-----------------------------------------------------------------
// list_63.c:
//     半角カナ文字の検査、全角への変換ルーチン
//                Last Update: <2004/11/20 11:06:36 A.Murakami>
//-----------------------------------------------------------------
#include <stdio.h>
//-----------------------------------------------------------------
// 文字列検査用マクロ
//-----------------------------------------------------------------
#define KANA "\
。「」、・ヲァィゥェォャュョッーアイウエオカキクケコ\
サシスセソタチツテトナニヌネノハヒフヘホマミムメモ\
ヤユヨラリルレロワン゛゜"
#define iskanji(c)       (((c)^0x20)-0xa1u< 60)
#define iskana(c)        ((c)-0xa1u < 63)
#define isdaku(c)        (((c)&0xff) == 0xde)
#define ishandaku(c)     (((c)&0xff) == 0xdf)
#define maybedaku(c)     ((c)-0xb6u < 15 || (c)-0xcau < 5)
#define maybehandaku(c)  ((c)-0xcau < 5)
//-----------------------------------------------------------------
// 文字の種類[英数字, 全角, 半角カナ, 半角カナ(濁音,半濁音)]: SJIS
//-----------------------------------------------------------------
enum CKK_TYPE {
    CKK_ASCII = 0, CKK_KANJI = 1,
    CKK_KANA  = 2,
    CKK_KANA1 = 3, CKK_KANA2 = 4,
};
//-----------------------------------------------------------------
// 文字の種類を調べる[漢字,カナ,英数字,半角カナ]: SJIS
int CheckCKKcode(unsigned char in_c,unsigned char nxt_c);
// 半角カナから全角へ
void hk2zk(int hkey,char* z_code,int iPos,unsigned char c);
// ファイル中の文字数のカウント
int str_count(char* fname);
// 入力ファイルから文字列の取得
void read_string(char* fname,int read_sc,char* inbuf);
//-----------------------------------------------------------------

int main(void)
{
    char fname[] = "hankaku.txt";
    int  i,iPos,hkey,read_sc;
    char *h_code,*z_code;
    unsigned char c,nxt_c;
    // 入力ファイルの文字数取得
    read_sc=str_count(fname);
    // 文字配列の確保
    h_code = (char*)calloc(read_sc+1,sizeof(char));
    z_code = (char*)calloc(read_sc*2,sizeof(char));
    // 入力ファイルから文字列の取得
    read_string(fname,read_sc,h_code);
    // 変換
    for(i=0,iPos=0;i<read_sc;i++){
        c = h_code[i];
        nxt_c = (i<read_sc-1) ? h_code[i+1]: 0;
        if(hkey = CheckCKKcode(c,nxt_c)){
            switch(hkey){
            case CKK_KANJI: // 全角文字
                z_code[iPos++] = c;
                z_code[iPos++] = nxt_c;
                i++; break;
            case CKK_KANA: // カナ
                hk2zk(hkey,z_code,iPos,c);
                iPos += 2;
                break;
            case CKK_KANA1: case CKK_KANA2: // 濁音/半濁音
                hk2zk(hkey,z_code,iPos,c);
                iPos += 2;
                i++; // 半角2文字必要[ガ,パ ⇔ ア]
                break;
            }
        } else {
            // 英数字の場合は大文字に変換
            z_code[iPos++] = toupper(c);
        }
    }
    z_code[iPos] = 0;
    fputs(z_code,stdout);
    // 後始末
    free(h_code);
    free(z_code);
    return 0;
}

//-----------------------------------------------------------------
// 文字の種類を調べる[漢字,カナ,英数字,半角カナ]: SJIS
//-----------------------------------------------------------------
int CheckCKKcode(unsigned char in_c,unsigned char nxt_c)
{
    if(iskanji(in_c)) return CKK_KANJI;
    if(iskana(in_c)){
        if(maybedaku(in_c) && isdaku(nxt_c))
            return CKK_KANA1;
        if(maybehandaku(in_c) && ishandaku(nxt_c))
            return CKK_KANA2;
        return CKK_KANA;
    }
    return CKK_ASCII;
}
//-----------------------------------------------------------------
// 半角カナ文字から全角へ
//-----------------------------------------------------------------
void hk2zk(int hkey,char* z_code,int iPos,unsigned char c)
{
    char* p = KANA + (c-0xa1) * 2;
    z_code[iPos] = p[0]; z_code[iPos+1] = p[1];
    if(hkey==CKK_KANA1) z_code[iPos+1]++;
    if(hkey==CKK_KANA2) z_code[iPos+1]+=2;
}

//-----------------------------------------------------------------
// ファイル中の文字数のカウント
//-----------------------------------------------------------------
int str_count(char* fname)
{
    FILE* fp;
    int rsc,sum_sc = 0;
    char buf[BUFSIZ];
    memset(buf,0,BUFSIZ);
    if((fp=fopen(fname,"r"))==NULL){
        perror("read file");
        return 0;
    }
    while((rsc=fread(buf,sizeof(char),BUFSIZ,fp))){
        sum_sc += rsc;
    }
    sum_sc += rsc;
    fclose(fp);
    return sum_sc;
}
//-----------------------------------------------------------------
// 入力ファイルから文字列の取得
//-----------------------------------------------------------------
void read_string(char* fname,int read_sc,char* inbuf)
{
    FILE* fp;
    int rsc;
    if((fp=fopen(fname,"r"))==NULL) return;
    rsc = fread(inbuf,sizeof(char),read_sc,fp);
    if(rsc!=read_sc) perror("read size");
    fclose(fp);
}

半角カナを含む文章(hankaku.txt)
英数字を含む文字列:

When he smiled with NIYARI, he lifted the glasses of a black spot and
floated a haughty expression. Where [ of such a fellow ] will be said
"Really trust"? A command of a superior official still cannot oppose
absolutely and poor. It is being [ such YATSU- of I CHI O U - / a
superior official ] DA mosquito RA-. The moment such thinking emerged on
the head, it has appeared in expression. It seems that he also has full
knowledge of my thinking enough by years of association, and the present
thinking is also already read. When considering soon, my life began to
turn around a corner of a street greatly from this moment. Although it
is the thing of the future, it will be known personally that just the
slack of this momentary mind was fatal.


日本語文章(半角カナ含む):

彼はニヤリと微笑むと、黒斑の眼鏡を持ち上げ不遜な表情を浮かべた。一体、こん
な奴のどこを信用しろと言うのであろうか?それでも、上司の命令は絶対であり
下手に逆らうことはできない。こんなヤ・ツ・でも、イ・チ・オ・ウ・は、上司なの
ダ・カ・ラ・。
と、そんな思考が頭に浮かび上がった瞬間、それが表情に出てしまった。長年の
付き合いで彼は私の思考も十分熟知しており、現在の思考もすでに読まれている
ようだ。今に思えばこの瞬間から、私の人生は大きく曲がり角を回り始めたので
ある。後々のことであるが、この一瞬の気の緩みこそが命取りであった、という
ことを身をもって知ることになる。

変換例
英数字を含む文字列:

WHEN HE SMILED WITH NIYARI, HE LIFTED THE GLASSES OF A BLACK SPOT AND
FLOATED A HAUGHTY EXPRESSION. WHERE [ OF SUCH A FELLOW ] WILL BE SAID
"REALLY TRUST"? A COMMAND OF A SUPERIOR OFFICIAL STILL CANNOT OPPOSE
ABSOLUTELY AND POOR. IT IS BEING [ SUCH YATSU- OF I CHI O U - / A
SUPERIOR OFFICIAL ] DA MOSQUITO RA-. THE MOMENT SUCH THINKING EMERGED ON
THE HEAD, IT HAS APPEARED IN EXPRESSION. IT SEEMS THAT HE ALSO HAS FULL
KNOWLEDGE OF MY THINKING ENOUGH BY YEARS OF ASSOCIATION, AND THE PRESENT
THINKING IS ALSO ALREADY READ. WHEN CONSIDERING SOON, MY LIFE BEGAN TO
TURN AROUND A CORNER OF A STREET GREATLY FROM THIS MOMENT. ALTHOUGH IT
IS THE THING OF THE FUTURE, IT WILL BE KNOWN PERSONALLY THAT JUST THE
SLACK OF THIS MOMENTARY MIND WAS FATAL.


日本語文章(半角カナ含む):

彼はニヤリと微笑むと、黒斑の眼鏡を持ち上げ不遜な表情を浮かべた。一体、こん
な奴のどこを信用しろと言うのであろうか?それでも、上司の命令は絶対であり
下手に逆らうことはできない。こんなヤ・ツ・でも、イ・チ・オ・ウ・は、上司なの
ダ・カ・ラ・。
と、そんな思考が頭に浮かび上がった瞬間、それが表情に出てしまった。長年の
付き合いで彼は私の思考も十分熟知しており、現在の思考もすでに読まれている
ようだ。今に思えばこの瞬間から、私の人生は大きく曲がり角を回り始めたので
ある。後々のことであるが、この一瞬の気の緩みこそが命取りであった、という
ことを身をもって知ることになる。
inserted by FC2 system