[部分文字列]の検索結果


C言語のstrncpy関数やmemcpy関数ではバイト単位の操作になるので、漢字、ひらがな、カタカナなどの全角文字を文字数で指定して部分文字列を取り出すことができません。 そこで半角英数も全角文字も1文字として部分文字列を取り出すことができる関数を作成します。

以下はそのコードです。[C言語]UTF-8でエンコードされた文字列の文字数を取得するコードと同様に、文字の1バイト目のビットの状態を調べることによってその文字が何バイト文字を判定しています。

#include <stdio.h>
#include <string.h>

char *substr_utf8(char *dest, char *src, int offset, int len);
int _bytesize(unsigned char code);


int main(void)
{
    char *testStr = "ABCDEFGあいうえおアイウエオ愛夢佐々木";
    char strBuf[256];

    memset(strBuf, 0sizeof strBuf);

    printf("substr_utf8($testStr, 0, 5) = %s\n", substr_utf8(strBuf, testStr, 05));
    printf("substr_utf8($testStr, 3, 3) = %s\n", substr_utf8(strBuf, testStr, 33));
    printf("substr_utf8($testStr, 10, 4) = %s\n", substr_utf8(strBuf, testStr, 104));
    printf("substr_utf8($testStr, 13, 5) = %s\n", substr_utf8(strBuf, testStr, 135));

    return 0;
}

/* UTF-8でエンコードされた文字列の部分文字列を取り出す */
/* substr_utf8 (文字列式, オフセット, 長さ)*/
char *substr_utf8(char *dest, char *src, int offset, int len)
{
    int srclen = strlen(src);
    int pos = 0;
    int count = 0;
    char *cp = dest;

    while (pos < srclen) {
        unsigned char code;
        code = *(src + pos); /* ASCIIコード値を取得 */
        int bytelen = _bytesize(code);

        if (count >= offset && count < (offset + len)) {
            memcpy(cp, (src + pos), bytelen);
            cp += bytelen;
            *cp = '\0';
        }
        pos += bytelen;
        count++; /* 文字数をカウント */
    }

    return dest;
}

/* 文字のバイト長を求める */
int _bytesize(unsigned char code)
{
    int size = 1;
    int i;

    if (0x80 & code) { /* 1バイト文字以外 */
        for (i = 2; i <= 8; i++) {
            code <<= 1;
            if (!(0x80 & code)) {
                break;
            }
            size++;
        }
    }
    return size;
}

実行結果
$ ./substr_utf8
substr_utf8($testStr, 0, 5) = ABCDE
substr_utf8($testStr, 3, 3) = DEF
substr_utf8($testStr, 10, 4) = えおアイ
substr_utf8($testStr, 13, 5) = イウエオ愛

[2324] Posted by kagahiro at 2013/07/02 11:02:48
0 point | Link (3) | Trackback (0) | Comment (0)

Perlのsubstr関数ではバイト単位の操作になるので、漢字、ひらがな、カタカナなどの全角文字を文字数で指定して部分文字列を取り出すことができません。それでは不都合なことも多いので、半角英数も全角文字も1文字として部分文字列を取り出すことができる関数を作成します。

以下はそのコードです。[Perl]UTF-8でエンコードされた文字列の文字数を取得するコードと同様に、文字の1バイト目のビットの状態を調べることによってその文字が何バイト文字を判定しています。

#!/usr/bin/perl

use strict;
use warnings;

my $testStr = "ABCDEFGあいうえおアイウエオ愛夢佐々木";

print "substr_utf8($testStr, 0, 5) = " . substr_utf8($testStr, 0, 5), "\n";
print "substr_utf8($testStr, 3, 3) = " . substr_utf8($testStr, 3, 3), "\n";
print "substr_utf8($testStr, 10, 4) = " . substr_utf8($testStr, 10, 4), "\n";
print "substr_utf8($testStr, 13, 5) = " . substr_utf8($testStr, 13, 5), "\n";
print "substr_utf8($testStr, 13) = " . substr_utf8($testStr, 13), "\n";

exit;

# UTF-8でエンコードされた文字列の部分文字列を取り出す
# substr_utf8 (文字列式, オフセット[, 長さ])長さを指定しなかった場合は最後まで
sub substr_utf8 {
    my ($src, $offset, $len) = @_;

    my $srclen = length($src);
    my $pos = 0;
    my $count = 0;
    my $dest = '';

    while ($pos < $srclen) {
        my $code = ord substr($src, $pos, 1); # 先頭のASCIIコード値を取得
        my $bytelen = _bytesize($code);
        if (defined($len)){
            if ($count >= $offset && $count < ($offset + $len)) {
                $dest .= substr($src, $pos, $bytelen);
            }
        } else { # 長さ指定なし
            if ($count >= $offset) {
                $dest .= substr($src, $pos, $bytelen);
            }
        }
        $pos += $bytelen;
        $count++; # 文字数をカウント
    }

    return $dest;
}

# 文字のバイト長を求める
sub _bytesize {
    my $code = shift;
    my $size = 1;
    if (0x80 & $code) { # 1バイト文字以外
        $code <<= 1;
        for my $i (2 .. 8) {
            $size++;
            $code <<= 1;
            last if (!(0x80 & $code));
        }
    }
    return $size;
}

substr_utf8関数では、substr関数を使用して1バイト目のASCIIコード値を取得し、 _bytesize関数を呼び出して文字のバイト数を求め、その文字がパラメータで指定された範囲の場合は、戻り値として返す文字列に連結し、そうでなかった場合は文字数のカウントアップのみ行なっています。

_bytesize関数ではパラメータで渡されたコード値の場合の文字のバイト数を、コード値のビットの状態から判定し戻り値として返しています。

もっと自在にサーバを使い倒す 業務に役立つPerl (Software Design plus)
技術評論社 著者:木本 裕紀


amazon.co.jpのカスタマーレビューを見る
powered by amalink

[2244] Posted by kagahiro at 2012/12/13 10:51:25
0 point | Link (4) | Trackback (0) | Comment (0)

  1  


アクセスランキング

今日のアクセスランキング TOP 10

  1. FC2まとめ (4 PV)
  2. Twitter Lite - 起動時や利用時の読み込み速度が最大30%アップ (3 PV)
  3. 2ちゃんねる(2ch) (3 PV)
  4. 大人気のブランド品即時買取サービス「CASH」がDMM.comにたったの70億円で買い叩かれる (2 PV)
  5. 無料ダイヤルアッププロバイダ「Soloot(ソルート)」 (2 PV)
  6. ほしい物リスト (2 PV)
  7. SQLのSELECT文で先頭から上位(TOP)10件のレコードを取得する方法(SQL Server、Oracle、MySQL、PostgreSQL) (2 PV)
  8. 掲示板CGI ThreadPlus 1.2 のリリース (2 PV)
  9. RDB(リレーショナルデータベース) (2 PV)
  10. 入金0円ですぐにFXが始められる初心者におすすめの海外FXブローカー「XM」 #MT4 #MT5 #口座開設 (2 PV)

今月のアクセスランキング TOP 10

  1. FC2まとめ (12 PV)
  2. 将棋ウォーズPCブラウザ版がchrome、Firefox、edgeなどに対応 (8 PV)
  3. 掲示板CGI ThreadPlus 1.2 のリリース (5 PV)
  4. 「Kindle for the Web」 (5 PV)
  5. SQLのSELECT文で先頭から上位(TOP)10件のレコードを取得する方法(SQL Server、Oracle、MySQL、PostgreSQL) (5 PV)
  6. Jipanguの配布は終了しました (4 PV)
  7. [FX]裁量ポジションを簡単に管理できるMT4向け無料の裁量補助EA「PositionKeeper」 (4 PV)
  8. Twitter Lite - 起動時や利用時の読み込み速度が最大30%アップ (3 PV)
  9. 「さくらのクラウド」のオプションサービスで「専有ホスト」の提供を開始 (3 PV)
  10. ドル円(USDJPY)で爆益を狙うハイリスクハイリターンのMT4向けナンピンマーチンEA「Hyper Dollar」 (3 PV)

アクセス統計

ディレクトリ

関連サイト