Thinkers'Studio
JavaとC言語の自習ツール
全角半角が混在する文字列の一部を取り出す

文字列の一部分を取り出す−−subString

 Javaには文字列の一部分を取り出すメソッドsubStringが用意されていますが、c言語にはありません。同様の機能をTips 42でも取り上げましたが、今回は全角文字と半角文字が混在する文字列でも処理できるようにします。

【 全角文字も処理できるsubString 】
#include <stdio.h>
#include <string.h>

int chWidth( unsigned char *p )
{
    //  EUC-JP
    if( *p == '\0' ) return 0;
    if( *p & 0x80 ) return 2;
    return 1;

/*
    //  UTF-8
    if( *p == '\0' ) return 0;
    if( (*p & 0xFC) == 0xFC ) return 6;
    if( (*p & 0xF8) == 0xF8 ) return 5;
    if( (*p & 0xF0) == 0xF0 ) return 4;
    if( (*p & 0xE0) == 0xE0 ) return 3;
    if( (*p & 0xC0) == 0xC0 ) return 2;
    if( (*p & 0x80) == 0 ) return 1;
    return 0;

    //  Shift-JIS
    if( *p == '\0' ) return 0;
    if( 0x81 <= *p && *p <= 0x9F ) return 2;
    if( 0xE0 <= *p && *p <= 0xFC ) return 2;
    return 1;
*/
}

void mysubstring( char *t, char *s, int pos, int len )
{
    int     p1, p2, c, w;
    char    *p1c, *p2c;

    if( len < 1 ) {
        *t = '\0';
        return;
    }
    p1 = pos < 0 ? 0 : pos;
    p2 = pos + len;

    for( c = 0, p1c = s; c < p1; c++ ) {
        w = chWidth( p1c );
        if( w <= 0 ) {
            *t = '\0';
            return;
        }
        p1c += w;
    }
    for( p2c = p1c; c < p2; c++ ) {
        w = chWidth( p2c );
        if( w <= 0 ) break;
        p2c += w;
    }

    w = p2c - p1c;
    strncpy( t, p1c, w );
    *( t + w ) = '\0';
}

 文字列sのpos文字目からlen文字をtに取り出します。posやlenが文字列の外を指す場合でもできるだけ上手く動作するように配慮しました。
 使用する漢字コードによって全角半角を判断する方法が異なるので、文字の幅を調べる関数chWidthを使います。chWidthはポインタpが指す文字の幅が何バイトかを戻します。この関数の中にはEUC-JP、UTF-8、Shift-JIS用の処理を書いてありますので、使うときには必要な部分をコメントアウトしてください。

【クイズ】

【前回の答え】 実行結果はつぎのようになります。 (前回の問題を見る
    1
    5
    7
   11
   13
   17
   19
   23
   25
   29