[substr]の検索結果


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)

まずカタカナより比較的プログラミングしやすそうな英数字の全角半角変換から作成します。

半角から全角への変換の処理手順は、

・半角英数字の場合は、同じ全角英数字に置き換えて戻り値として返す文字列に連結
・それ以外の文字の場合はそのまま戻り値として返す文字列に連結

また、全角から半角への変換の処理手順は、

・全角英数字の場合は、同じ半角英数字に置き換えて戻り値として返す文字列に連結
・それ以外の文字の場合はそのまま戻り値として返す文字列に連結

となります。

文字コードはそれぞれ以下の通りですので、これらに該当する文字があったら置き換えを行います。

半角数字:0 - 9
30 - 39

全角数字:0 - 9
EFBC90 - EFBC99
2バイト目まではEFBC

半角アルファベット大文字:A - Z
41 - 5A

全角アルファベット大文字:A - Z
EFBCA1 - EFBCBA
2バイト目まではEFBC

半角アルファベット小文字:a - z
61 - 7A

全角アルファベット小文字:a - z
EFBD80 - EFBD9A
2バイト目まではEFBD

以下が英数字の半角から全角へ、全角から半角への変換を行うコード(プログラム)です。

#!/usr/bin/perl

use strict;
use warnings;
use Encode;

my $hanAlnum = "ABCDEい12345あabcde";
my $zenAlnum = "ABCDEい12345あabcdeカ";

my $zenstr = han2zen_alnum($hanAlnum);
Encode::from_to($hanAlnum, 'utf8', 'cp932');
Encode::from_to($zenstr, 'utf8', 'cp932');
print "$hanAlnum ---> $zenstr\n";

my $hanstr = zen2han_alnum($zenAlnum);
Encode::from_to($zenAlnum, 'utf8', 'cp932');
Encode::from_to($hanstr, 'utf8', 'cp932');
print "$zenAlnum ---> $hanstr\n";

# UTF-8でエンコードされた半角英数字を全角英数字に変換する
sub han2zen_alnum {
    my ($src) = @_;

    my $srclen = length($src);
    my $pos = 0;
    my $dest = '';
    while ($pos < $srclen) {
        my $code = ord substr($src, $pos, 1); # 先頭のASCIIコード値を取得
        my $bytelen = _bytesize($code);

        my $lastbyte = 0;
        my $bytechar = '';
        my $flagged_utf8 = ''; 
        if ($code >= 0x30 && $code <= 0x39) { # 数字
            $lastbyte = 0x90 + ($code - 0x30);
            $bytechar = pack("C3", 0xEF, 0xBC, $lastbyte);
            $dest .= $bytechar;
        }
        elsif ($code >= 0x41 && $code <= 0x5A) { # 大文字英字
            $lastbyte = 0xA1 + ($code - 0x41);
            $bytechar = pack("C3", 0xEF, 0xBC, $lastbyte);
            $dest .= $bytechar;
        
        }
        elsif ($code >= 0x61 && $code <= 0x7A) { # 小文字英字
            $lastbyte = 0x81 + ($code - 0x61);
            $bytechar = pack("C3", 0xEF, 0xBD, $lastbyte);
            $dest .= $bytechar;
        }
        else {
            $dest .= substr($src, $pos, $bytelen);
        }
        $pos += $bytelen;
    }

    return $dest;
}

# UTF-8でエンコードされた全角英数字を半角英数字に変換する
sub zen2han_alnum {
    my ($src) = @_;

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

    while ($pos < $srclen) {
        my $code = ord substr($src, $pos, 1); # 先頭のASCIIコード値を取得
        my $bytelen = _bytesize($code);
        my $hit = 0;
        if ($code == 0xEF) { # 全角英数の場合は1バイト目がEF
            my $code2 = ord substr($src, $pos + 1, 1);  # 2バイト目
            my $code3 = ord substr($src, $pos + 2, 1);  # 3バイト目
            if ($code2 == 0xBC) {
                if ($code3 >= 0x90 && $code3 <= 0x99) {
                    $dest .= chr(0x30 + ($code3 - 0x90));
                    $hit = 1;
                }
                elsif ($code3 >= 0xA1 && $code3 <= 0xBA) {
                    $dest .= chr(0x41 + ($code3 - 0xA1));
                    $hit = 1;
                }
            }
            elsif ($code2 == 0xBD) {
                if ($code3 >= 0x80 && $code3 <= 0x9A) {
                    $dest .= chr(0x61 + ($code3 - 0x80));
                    $hit = 1;
                }
            }
        }
        if(!$hit) {
            $dest .= substr($src, $pos, $bytelen);
        }
        $pos += $bytelen;
    }

    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;
}

[2250] Posted by kagahiro at 2012/12/19 16:54:42
0 point | Link (1) | Trackback (0) | Comment (0)

Unicodeの文字コード表によるとUTF-8の半角英数、全角英数、半角カナ、全角カナの文字コードは以下のようになるようです。 英数字の場合は半角と全角の文字がそれぞれ対応していますが、カタカナの場合は半角と全角では文字の数が違うようです。

半角数字:0 - 9
30 - 39

全角数字
EFBC90 - EFBC99
2バイト目まではEFBC

半角アルファベット大文字:A - Z
41 - 5A

全角アルファベット大文字:A - Z
EFBCA1 - EFBCBA
2バイト目まではEFBC

半角アルファベット小文字:a - z
61 - 7A

全角アルファベット小文字:a - z
EFBD80 - EFBD9A
2バイト目まではEFBD

半角カナ(JISカナ)
EFBDA1 - EFBE9F
1バイト目がEFで2バイト目、3バイト目がBDA1 - BE9Fの範囲

全角カタカナ
E38299 - E383BF
1バイト目がE3で2バイト目、3バイト目が82A1 - 83BFの範囲

Unicode対応 文字コード表
http://ash.jp/code/unitbl1.htm
http://ash.jp/code/unitbl21.htm

動作確認用にまずUTF-8の文字コードを表示するプログラムを作成します。

#!/usr/bin/perl

use strict;
use warnings;
use Encode;

my $hanAlnum = "ABCDE12345abcde";
my $zenAlnum = "ABCDE12345abcde";
my $hanKana = "アイウエオ";
my $zenKana = "アイウエオ";

print_charcode($hanAlnum);
print "\n";

print_charcode($zenAlnum);
print "\n";

print_charcode($hanKana);
print "\n";

print_charcode($zenKana);
print "\n";

# UTF-8でエンコードされた文字列の文字コードを表示する
sub print_charcode {
    my ($src) = @_;

    my $srclen = length($src);
    my $pos = 0;

    while ($pos < $srclen) {
        my $code = ord substr($src, $pos, 1); # 先頭のASCIIコード値を取得
        my $bytelen = _bytesize($code);
        my $srcchar = substr($src, $pos, $bytelen);
        my $codestr = sprintf("%2.2X ", $code);
        if ($bytelen > 1) {
            my $times = $bytelen - 1;
            for my $i (1 .. $times) {
                my $charcode = ord substr($src, $pos + $i, 1);
                $codestr .= sprintf("%2.2X ", $charcode);
            }
        }

        # Windowsで表示するのでcp932(シフトJIS)に変換
        Encode::from_to($srcchar, 'utf8', 'cp932');
        print "$srcchar : $codestr\n";
        $pos += $bytelen;
    }
}

# 文字のバイト長を求める
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;
}

Perl Hacks ―プロが教えるテクニック & ツール101選
オライリー・ジャパン 著者:chromatic,Damian Conway,Curtis "Ovid" Poe


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

[2248] Posted by kagahiro at 2012/12/17 00:25:00
0 point | Link (1) | Trackback (0) | Comment (0)

Perlのsubstr関数ではバイト単位の操作になるので、漢字、ひらがな、カタカナなどの全角文字を文字数で指定して部分文字列を取り出すことができません。それでは不都合なことも多いので、半角英数も全角文字も1文字と...
[2244] Posted by kagahiro at 2012/12/13 10:51:25
0 point | Link (4) | Trackback (0) | Comment (0)

Perlのlength関数ではバイト単位となるので、UTF-8でエンコードされている場合、漢字、ひらがな、カタカナなどは1文字で3となってしまいます。ブログなどのアプリケーションのテキスト処理ではそれでは不都合な場合も...
[2243] Posted by kagahiro at 2012/12/12 11:56:21
1 point | Link (3) | Trackback (0) | Comment (1)

まず、今回のクイズしりとりに勝つため私が考えた作戦は、相手(コンピュータ)に、先頭に使用されているより末尾に使用されている数が多いアルファベットの単語から選ばせるようにすれば、そのうち相手が手詰まり...
[2003] Posted by kagahiro at 2010/08/23 17:18:13
0 point | Link (1) | Trackback (0) | Comment (0)

  1  


アクセスランキング

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

  1. 嬉野流開発者のたまごんさんがソフト指し疑惑で将棋倶楽部24のアカウントを停止されてしまう #将棋 (3 PV)
  2. Tumblr(タンブラー)のダッシュボードからおすすめ投稿を消す(非表示にする)方法 (2 PV)
  3. 有力将棋系ユーチューバーのショウヤンさんが将棋ウォーズで「ソフト指し」を告白し衝撃走る (2 PV)
  4. 株価指数 (1 PV)
  5. [Perl]UTF-8でエンコードされた文字列の文字数を取得するコード (1 PV)
  6. [将棋]角換わり▲4五桂速攻(△6五桂速攻) #佐藤天彦名人 #三浦弘行九段 (1 PV)
  7. Google News (グーグルニュース)日本版 (1 PV)
  8. 将棋倶楽部24がフィッシャールール(早指し3)導入 (1 PV)

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

  1. SQLのSELECT文で先頭から上位(TOP)10件のレコードを取得する方法(SQL Server、Oracle、MySQL、PostgreSQL) (1875 PV)
  2. USTREAM(ユーストリーム) 日本語版 無料のライブ映像配信サービス (385 PV)
  3. Google News (グーグルニュース)日本版 (306 PV)
  4. [将棋]角換わり▲4五桂速攻(△6五桂速攻) #佐藤天彦名人 #三浦弘行九段 (219 PV)
  5. Tumblr(タンブラー)のダッシュボードからおすすめ投稿を消す(非表示にする)方法 (207 PV)
  6. 最新のGoogle News(グーグルニュース)日本版のRSSが取得できるURL (194 PV)
  7. 有力将棋系ユーチューバーのショウヤンさんが将棋ウォーズで「ソフト指し」を告白し衝撃走る (179 PV)
  8. [Perl]UTF-8でエンコードされた文字列の文字数を取得するコード (145 PV)
  9. ウェブページを1回だけリロード(再表示)する方法 (139 PV)
  10. グーグルニュース(Google News)日本版が表示できるURL (131 PV)

アクセス統計

ディレクトリ

関連サイト