2014 年 1月 の投稿一覧

kusano

初投稿となります、クライゼルグループの kusano です。

何を書こうか考えたのですが、PHP の文字列チェック関数について少し気になったことがあったので、この機会に簡単な調査をしてみました。

PHP で文字列がどういった文字で構成されているかを確認する関数として有名なのは preg_match でしょうか。正規表現によるマッチングを行えるので万能ですね。

一方、文字列が「0 から 9 の数字」のみで構成されているかどうかのみをチェックする代わりに速い (らしい) 関数として ctype_digit といったものもあると聞きました。

以下では、ctype_digit 関数とはそもそもどういった関数かをまとめた上で、preg_match との速度比較を行ってみようと思います。

ctype_digit とは

ctype_digit 関数の仕様については こちら に書いてある通りで、「与えられた文字列 text のすべての文字が数字であるかどうかを調べます。」となります。

ただ、リンク先ページの「注意」にも書いてあるとおり、気をつけるべき点があります。以下に引用します。

  • 注意:
    • この関数を活用するには string を渡さなければなりません。 たとえば integer を渡すと、期待する結果にならない可能性があります。 HTML フォームに入力された整数値は、integer ではなく string 型で返されます。 マニュアルの 型 についての節を参照ください。
    • -128 から 255 までの整数値を渡すと、ひとつの文字の ASCII 値とみなします (負の値には 256 を足して、拡張 ASCII の範囲に収まるようにします)。 それ以外の整数値は、10 進数を含む文字列とみなします。

つまり、-128 から 255 までの整数値を ctype_digit に渡してしまうと、文字列が 0 から 9 の数字のみで構成されているかどうかではなく、その ASCII 値に対応する文字列が 0 から 9 の数字かどうか、がチェックされるというわけですね。

実際に簡単なプログラムを動かして ctype_digit の振る舞いを見てみます。

<?php

for ($i = -512; $i <= 512; $i++) {
    if ($i < 256 and $i > -129) {
        echo "ASCII Code: ";
        echo chr($i);
    } else {
        echo "Non ASCII Code";
    }
    
    echo " ($i): ";
    var_dump ( ctype_digit($i) );
}

上記のコードを実行すると、以下のような結果が出ます。 (長いので一部割愛します)


Non ASCII Code (-512): bool(false)   ← ASCII 値とは扱わないが 
Non ASCII Code (-511): bool(false)      "-" が含まれるので false
             :
Non ASCII Code (-129): bool(false)
ASCII Code: <80> (-128): bool(false) ← ASCII 値として扱い、
ASCII Code: <81> (-127): bool(false)    0-9 の文字ではないので false
             :
ASCII Code:  (-2): bool(false)
ASCII Code:  (-1): bool(false)
ASCII Code: ^@ (0): bool(false)
             :
ASCII Code:   (32): bool(false)
ASCII Code: ! (33): bool(false)
             :
ASCII Code: . (46): bool(false)
ASCII Code: / (47): bool(false)
ASCII Code: 0 (48): bool(true)  ← ASCII 値として扱い、
             :                     0-9 の文字なので true
ASCII Code: 1 (49): bool(true)
ASCII Code: 9 (57): bool(true)
ASCII Code: : (58): bool(false) ← ASCII 値として扱い、
ASCII Code: ; (59): bool(false)    0-9 の文字ではないので false
ASCII Code: < (60): bool(false)
             :
ASCII Code:  (254): bool(false)
ASCII Code:  (255): bool(false)
Non ASCII Code (256): bool(true)  ← ASCII 値と扱わず、0-9 の文字だけで
Non ASCII Code (257): bool(true)     構成されると見なされ true
             :

実際にこういったプログラムを書いてみると、どういった動きになるかひと目で分かりますね。

なお、float 型や bool 型はどの値を与えても false が返ります。

したがって、ctype_digit を利用する場合、あえて「ASCII 値に対応する文字列が 0 から 9 の数字かどうかをチェック」するのでない限り、値を必ず string 型にしてから渡すようにするよう注意が必要ということですね。

ちなみに、preg_match に string 型以外を渡すと、string 型にキャストして判定されるようです。

ctype_digit と preg_match との速度比較

ctype_digit と preg_match との速度比較 としては、ctype digit と preg matchでの文字列比較速度 で比較検証がされていますね。こちらの結果によるとほとんど両者の速度は変わらないそうです。

ただ、こちらで紹介している方法ですと、それぞれの関数による処理時間に加え、以下の処理時間も計測に含まれているようです。

  • 文字列の生成処理
  • echo による出力処理

仮に上の 2 つの処理が ctype_digit と preg_match に比べて数倍以上時間がかかってるとすると、2つの関数の処理時間の差が埋もれてしまっているかもしれませんね。

そんなわけで、ctype digit と preg matchでの文字列比較速度 で紹介されているコードから、echo による出力を省き、文字列生成と文字列チェックのそれぞれの処理の前後に microtime 関数を入れて、それぞれにかかる時間を計測できるようにしたコードで改めて計測を行ってみました。

検証に使用したコード

【string_generator2.php】

<?php

function generate_random_strings($type='letters')
{
    switch($type){
      case 'digits':
        $asset = '0123456789';
        break;
      case 'letters':
      default:
        $asset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        break;
    }

    $length = strlen($asset);
    $max = rand(4, 32);
    $result = array();
    for($i = 0; $i < $max; $i++){
        array_push($result, $asset[rand(0, $length-1)]); 
    }

    return implode($result);
}

function generate_list($max=100, $type='letters')
{
  $start_time = microtime(true);
  $result = array();
  for($i = 0; $i < $max; $i++){
    array_push($result, generate_random_strings($type));
  }
  echo "str_gen:\t";
  echo microtime(true) - $start_time . " sec\n";
  return $result;
}

function generate_letters_list($max=100)
{
  return generate_list($max);
}

function generate_digits_list($max=100)
{
  return generate_list($max, 'digits');
}

【ctype_digit_bench.php】

<?php

require_once('string_generator2.php');

function validate($variables)
{
  $start_time = microtime(true);
  foreach($variables as $v){
    if(ctype_digit($v)){
      $valid++;
    }
    else{
      $invalid++;
    }
  }

  echo "ctype_digit:\t";
  echo microtime(true) - $start_time . " sec\n";

  echo "# valid:   $valid\n";
  echo "# invalid: $invalid\n";
}

validate(generate_letters_list(100000));
validate(generate_digits_list(100000));

【preg_match_bench.php】

<?php

require_once('string_generator2.php');

function validate($variables)
{
  $start_time = microtime(true);
  foreach($variables as $v){
    if(preg_match('/^[0-9]+$/', $v)){
      $valid++;
    }
    else{
      $invalid++;
    }
  }

  echo "preg_match:\t";
  echo microtime(true) - $start_time . " sec\n";

  echo "# valid:   $valid\n";
  echo "# invalid: $invalid\n";
}

validate(generate_letters_list(100000));
validate(generate_digits_list(100000));

上記のコードによる計測内容は要約すると以下のようになります。こちらの 1,2 をそれぞれ時間計測しています。

  1. 10万 x 2 行のランダム文字列を生成(generate_letters_list および generate_digits_list 関数)し、validate 関数に渡す
  2. validate 関数内で、それぞれ ctype_digit と preg_match で文字列の検査を実施

検証した環境

上記のコードを、以下の環境で 10 回実施し、その平均値をとってみました。

  • OS : CentOS 6.2
  • CPU : Intel Core2Duo 3.33GHz
  • Memory : 512MB
  • PHP : Ver.5.3.3

検証結果

  • ctype_digit_bench.php
    • A-Z, a-z, 0-9 で構成されたランダム文字列 10 万行を生成・チェック
      • 文字列生成: 6.28 秒
      • ctype_digit: 0.175 秒
    • 0-9 で構成されたランダム文字列 10 万行を生成・チェック
      • 文字列生成: 6.29 秒
      • ctype_digit: 0.170 秒
  • preg_match_bench.php
    • A-Z, a-z, 0-9 で構成されたランダム文字列 10 万行を生成・チェック
      • 文字列生成: 6.32 秒
      • preg_match: 0.274 秒
    • 0-9 で構成されたランダム文字列 10 万行を生成・チェック
      • 文字列生成: 6.46 秒
      • preg_match: 0.289 秒

この結果から、以下のように考えられるのではないかと思われます。

  • 文字列生成は文字列チェック (ctype_digit と preg_match) に比べ、10 倍以上時間がかかる
  • ctype_digit の方が preg_match より 1.5 倍程度速い

参考にさせていただいたサイトでの検証ですと、前者の点で ctype_digit と preg_match の差が文字列生成側の誤差の範囲内になってしまっていたのかもしれませんね。

ctype_digit の方が単機能なので当たり前といえば当たり前ですが、一応これで ctype_digit と preg_match との正味のチェックの処理時間の差が確認できたかと思います。

まとめ

計測の結果、ctype_digit は preg_match の 1.5 倍程度速いようでした。ただ、preg_match のように int 型で渡した場合に string 型と同じようには判定してくれませんので、利用する際は注意が必要になりますね。

以上、今更ネタかもしれませんが、何かのお役に立てれば幸いです。

Tags: , ,

black

明けましておめでとうございます。black です。

今回は業務に使うツール作成をしてみました。このツールは複数行にリスト化された文字列に対して、各行ごとに含まれる文字種を判定するものです。
テキストデータに意図しない文字種のデータが含まれていないかを確認したい場合があり、業務効率化と勉強がてらに作ってみました。

目次

  1. ツール作り
  2. 使い方
  3. ソース全文

ツール作り

ツールはインターフェイスの作成が不要な EXCEL の VBA で作ることにします。

まずはざっくりと仕様を以下のように決めました。

  • 1 列目のセルを、1 行目から入力行数分まで処理する
  • 入力文字を「全角文字」「半角英数」「全角半角の混在」の種別ごとにおおまかに分ける
  • 全角ひらがな、全角カタカナ、半角文字、半角カナ、半角記号に分類して抽出する
  • 各列の説明を一行目に挿入する (既に説明行がある場合はスキップ)

*完成イメージ

lab_img2

まずは半角か全角か混合かの判定を作成します。

'ANSI文字列に変換した文字列を取得
  set_text_ansi = StrConv(set_text, vbFromUnicode)
  
  If Len(set_text) = LenB(set_text_ansi) Then  '半角のみ
      ~
  ElseIf Len(set_text) * 2 = LenB(set_text_ansi) Then  '全角のみ
      ~
  Else  '半角と全角の混合

ここは文字数とバイト数で比較判定する定番の手法を採用しました。

まずは入力文字が半角である場合を作成。

For l_int_1 = 1 To Len(set_text)
    my_temp = Mid(set_text, l_int_1, 1)
    If my_temp Like "[a-z]" Or my_temp Like "[A-Z]" Then
        han_temp = han_temp & my_temp
    ElseIf my_temp Like "[。-゚]" Then '半角カナの場合
        kana_temp = kana_temp & my_temp
    Else 'アルファベット以外
        kigo_temp = kigo_temp & my_temp
    End If
Next

入力文字を一文字ずつ抽出しLike演算子で判定、
英字、半角カナであればそれぞれの専用の変数に格納、
それ以外は半角記号と見なすようにしました。
注意点は、半角カナのLike演算子の範囲を[ア-ン]にしてしまうと、
濁点半濁点が無視されてしまうので、そこまで含んだ指定にするところでしょうか。

しかしここで数字を失念していたことが発覚。

ElseIf my_temp Like "#" Then
    ~

なのでLIKE演算子で0~9の場合の条件分岐を追加しました。
さらに数字のみの場合や、日付の場合にも処理も分けた方がよさそうだと思い分岐を追加。

If VarType(set_text) = 8 Then '項目が文字型の時
    ~
ElseIf VarType(set_text) = 7 Then '項目が日付型の時
    ~
Else '項目がそれ以外の型の時(数字とみなす)
    If InStr(set_text, ".") Then '小数を含む数字の場合
        result = "数字(小数)"
        Cells(i, int_cell).Value = "<ALL(小数)>"
    Else
        result = "数字"
        Cells(i, int_cell).Value = "<ALL>"
    End If
End If

ここではVarType関数を使いました。戻り値で変数の型などを返してくれるので、文字、日付、数字などを大別するには便利です。

半角の対応は以上です。

次は全角の場合の対応です。

If set_text = StrConv(set_text, vbHiragana) Then '全てひらがな
    ~
ElseIf set_text = StrConv(set_text, bvkatakana) Then '全てカタカナ
    ~
Else '全角混合

各入力値を、元の値と、ひらがな変換したものと比較して一致していればひらがなと判定、
カタカナも同様に、という手段を取ろうと思いましたが、これには落とし穴が。。。
テストしてみると、全角の記号や長音が含まれていた時それを識別できないことが判明。
結局はここもLIKE演算子で対応することに。

'検証文字をばらす
For l_int_1 = 1 To Len(set_text)
        my_temp = Mid(set_text, l_int_1, 1)
    If my_temp Like "[あ-ん]" Then '五十音ひらがな
        hira_temp = hira_temp & my_temp
    ElseIf my_temp Like "[ア-ン]" Then  '五十音カタカナ
        zenkana_temp = zenkana_temp & my_temp
    ElseIf my_temp Like "ー" Then '長音対応
        hira_temp = hira_temp & my_temp
        zenkana_temp = zenkana_temp & my_temp
    Else 'それ以外(全角記号など)
        str_temp = my_temp
    End If
Next

やることは半角の時と同様ですが、長音のみはひらがなとカタカナどちらにも属するようにしています。

これで全角の場合も完成です。

全角と半角が混合している場合は上記を組み合わせて対応。
さて、これで基礎は完成しました。

次は空白文字の対応です。
ここまでの対応で、全角、半角それぞれの空白文字も記号として振り分けはされるのですが、
ぱっと見た目には分かりません。
そこで、空白文字判定用のカラムを追加し、空白文字あれば”○”が入るように対応。

あとは結果表示の調整です。
分類したデータが続き文字でない場合に、わかりやすいように間にカンマを挟むモジュールを追加します。

Function add_comma(temp As Variant) As Variant
    If temp <> "" And Right(temp, 1) <> "," Then
        temp = temp & ","
    End If
    add_comma = temp
End Function

これを文字判定の都度実行させます。

それと、一行目に各列の説明を挿入するコードも入れておきます。

    '各列の説明行の追加
    chk_str_header = "検証文字列"
    If Cells(1, 1) <> chk_str_header Then
        Application.CutCopyMode = False
        Range("1:1").Insert
        With Cells(1, 1)
            .Value = chk_str_header
            .Interior.Color = RGB(255, 255, 0)
        End With
        With Cells(1, hantei_cell)
            .Value = "型判定"
            .Interior.Color = RGB(0, 255, 255)
        End With
        Cells(1, zenkaku_cell).Value = "他全角"
        Cells(1, zenhira_cell).Value = "ひらがな"
        Cells(1, zenkana_cell).Value = "全角カナ"
        Cells(1, hankaku_cell).Value = "半角文字"
        Cells(1, hankana_cell).Value = "半角カナ"
        Cells(1, kigo_cell).Value = "半角記号"
        Cells(1, int_cell).Value = "数字"
        Cells(1, space_cell).Value = "全角空白"
        With Range("A1:J1")
            .Font.Bold = True
            .Borders.LineStyle = xlContinuous
            .HorizontalAlignment = xlCenter
        End With
    End If

これで完成です。

使い方

Excel を開き、一番左の列に判別させたい文字列を入力します。

lab_img3

Visual Basic Editor に以下の ソース全文 を貼り付けて実行します。

実行した結果は以下のようになります。

lab_img1

カンマが含まれていた場合に見づらかったり、VBAなので処理速度がお察しの通りだったりと、
まだまだ問題もありますが、とりあえずは要求を満たすものができました。

専門職ではないので作りの甘い部分はありますが、
同じようなものが欲しい人の参考になればと思います。

ソース全文

Sub text_judge()
    Dim chk_str_header, my_temp, str_temp, hira_temp, zenkana_temp, num_temp, han_temp, kana_temp, kigo_temp As String
    Dim i, max_row, zenkaku_cell, zenhira_cell, zenkana_cell, hankaku_cell, hankana_cell, kigo_cell, int_cell, space_cell As Integer
    hantei_cell = 2     '型判定結果のcolumn位置
    zenkaku_cell = 3    '全角文字のcolumn位置
    zenhira_cell = 4    '全角ひらがなのcolumn位置
    zenkana_cell = 5    '全角カタカナのcolumn位置
    hankaku_cell = 6    '半角文字のcolumn位置
    hankana_cell = 7    '半角カナのcolumn位置
    kigo_cell = 8       '半角記号のcolumn位置
    int_cell = 9        '数字のcolumn位置
    space_cell = 10     '全角空白のcolumn位置
    
    '各列の説明行の追加
    chk_str_header = "検証文字列"
    If Cells(1, 1) <> chk_str_header Then
        Application.CutCopyMode = False
        Range("1:1").Insert
        With Cells(1, 1)
            .Value = chk_str_header
            .Interior.Color = RGB(255, 255, 0)
        End With
        With Cells(1, hantei_cell)
            .Value = "型判定"
            .Interior.Color = RGB(0, 255, 255)
        End With
        Cells(1, zenkaku_cell).Value = "他全角"
        Cells(1, zenhira_cell).Value = "ひらがな"
        Cells(1, zenkana_cell).Value = "全角カナ"
        Cells(1, hankaku_cell).Value = "半角文字"
        Cells(1, hankana_cell).Value = "半角カナ"
        Cells(1, kigo_cell).Value = "半角記号"
        Cells(1, int_cell).Value = "数字"
        Cells(1, space_cell).Value = "全角空白"
        With Range("A1:J1")
            .Font.Bold = True
            .Borders.LineStyle = xlContinuous
            .HorizontalAlignment = xlCenter
        End With
    End If
    
    max_row = ActiveSheet.UsedRange.Find("*", , xlFormulas, , xlByRows, xlPrevious).Row
    i = 2
    
    For i = 2 To max_row   'A列の最後まで繰り返し
        set_text = Cells(i, 1)
         
        '値がない場合はスキップ
        If Len(set_text) = 0 Then
            GoTo Continue
        End If
         
        'ANSI文字列に変換した文字列を取得
        set_text_ansi = StrConv(set_text, vbFromUnicode)
        
        'まず全角のみ、半角のみか判定
        
        If Len(set_text) = LenB(set_text_ansi) Then
        '半角だけの時
            If VarType(set_text) = 8 Then
                result = "半角英数"
                
                    '変数初期化
                    han_temp = ""
                    kana_temp = ""
                    kigo_temp = ""
                    num_temp = ""
                    
                    If set_text Like "* *" Then '半角スペース検索
                        Cells(i, space_cell).Value = "○"
                    End If
                    
                    '検証文字をばらす
                    For l_int_1 = 1 To Len(set_text)
                        my_temp = Mid(set_text, l_int_1, 1)
                        If my_temp Like "[a-z]" Or my_temp Like "[A-Z]" Then '半角英字の場合
                            han_temp = han_temp & my_temp
                            num_temp = add_comma(num_temp)
                            kana_temp = add_comma(kana_temp)
                            kigo_temp = add_comma(kigo_temp)
                            
                        ElseIf my_temp Like "[。-゚]" Then        '半角カナの場合
                            kana_temp = kana_temp & my_temp
                            num_temp = add_comma(num_temp)
                            han_temp = add_comma(han_temp)
                            kigo_temp = add_comma(kigo_temp)
                        
                        ElseIf my_temp Like "#" Then    '数字の場合
                            num_temp = num_temp & my_temp
                            han_temp = add_comma(han_temp)
                            kana_temp = add_comma(kana_temp)
                            kigo_temp = add_comma(kigo_temp)
                            
                        Else        'アルファベット以外
                            kigo_temp = kigo_temp & my_temp
                            han_temp = add_comma(han_temp)
                            kana_temp = add_comma(kana_temp)
                            num_temp = add_comma(num_temp)
                        
                        End If
                    Next
                                                                                       
                    Cells(i, hankaku_cell).Value = han_temp
                    Cells(i, hankana_cell).Value = kana_temp
                    Cells(i, kigo_cell).Value = kigo_temp
                    Cells(i, int_cell).Value = num_temp

                
            ElseIf VarType(set_text) = 7 Then   '項目が日付の時
                result = "日付"
                
            Else    '数字のみの場合、小数と整数に分ける
                If InStr(set_text, ".") Then
                    result = "数字(小数)"
                    Cells(i, int_cell).Value = "<ALL(小数)>"
                Else
                    result = "数字"
                    Cells(i, int_cell).Value = "<ALL>"
                End If
            End If
            
        ElseIf Len(set_text) * 2 = LenB(set_text_ansi) Then '全角
        
            my_temp = ""
            str_temp = ""
            hira_temp = ""
            zenkana_temp = ""
            
            '検証文字をばらす
            For l_int_1 = 1 To Len(set_text)
                my_temp = Mid(set_text, l_int_1, 1)
                    'ひらがな、カタカナ、長音、その他で処理を分ける
                    If my_temp Like "[あ-ん]" Then
                        hira_temp = hira_temp & my_temp
                        zenkana_temp = add_comma(zenkana_temp)
                        str_temp = add_comma(str_temp)
                    ElseIf my_temp Like "[ア-ン]" Then
                        zenkana_temp = zenkana_temp & my_temp
                        hira_temp = add_comma(hira_temp)
                        str_temp = add_comma(str_temp)
                    ElseIf my_temp Like "ー" Then
                        hira_temp = hira_temp & my_temp
                        zenkana_temp = zenkana_temp & my_temp
                        str_temp = add_comma(str_temp)
                    Else
                        str_temp = str_temp & my_temp
                        hira_temp = add_comma(hira_temp)
                        zenkana_temp = add_comma(zenkana_temp)
                    End If
            Next
                                           
            If set_text Like "* *" Then    '全角スペース検索
                Cells(i, space_cell).Value = "○"
            End If
            
            Cells(i, zenkaku_cell).Value = str_temp
            Cells(i, zenhira_cell).Value = hira_temp
            Cells(i, zenkana_cell).Value = zenkana_temp
            result = "全角文字"
            
        Else
            '半角全角混合の処理
            
            '初期化
            my_temp = ""
            str_temp = ""
            hira_temp = ""
            zenkana_temp = ""
            han_temp = ""
            kana_temp = ""
            kigo_temp = ""
            num_temp = ""
            
            '検証文字をばらす
            For l_int_1 = 1 To Len(set_text)
                my_temp = Mid(set_text, l_int_1, 1)
                If LenB(StrConv(my_temp, vbFromUnicode)) = 2 Then   '全角の場合
                
                    If my_temp Like "[あ-ん]" Then
                        hira_temp = hira_temp & my_temp
                        zenkana_temp = add_comma(zenkana_temp)
                        str_temp = add_comma(str_temp)
                    ElseIf my_temp Like "[ア-ン]" Then
                        zenkana_temp = zenkana_temp & my_temp
                        hira_temp = add_comma(hira_temp)
                        str_temp = add_comma(str_temp)
                    ElseIf my_temp Like "ー" Then
                        hira_temp = hira_temp & my_temp
                        zenkana_temp = zenkana_temp & my_temp
                        str_temp = add_comma(str_temp)
                    Else
                        str_temp = str_temp & my_temp
                        hira_temp = add_comma(hira_temp)
                        zenkana_temp = add_comma(zenkana_temp)
                    End If
                            
                    
                    han_temp = add_comma(han_temp)
                    han_temp = add_comma(han_temp)
                    kana_temp = add_comma(kana_temp)
                    kigo_temp = add_comma(kigo_temp)
                Else        '半角の場合
                    If my_temp Like "[a-z]" Or my_temp Like "[A-Z]" Then
                        han_temp = han_temp & my_temp
                        str_temp = add_comma(str_temp)
                        kana_temp = add_comma(kana_temp)
                        kigo_temp = add_comma(kigo_temp)
                        num_temp = add_comma(num_temp)
                    
                    ElseIf my_temp Like "[。-゚]" Then        '半角カナの場合
                        kana_temp = kana_temp & my_temp
                        han_temp = add_comma(han_temp)
                        kigo_temp = add_comma(kigo_temp)
                        num_temp = add_comma(num_temp)
                    
                    ElseIf my_temp Like "*#*" Then          '数字の場合
                        han_temp = add_comma(han_temp)
                        kana_temp = add_comma(kana_temp)
                        kigo_temp = add_comma(kigo_temp)
                        num_temp = num_temp & my_temp
                        
                    Else        'アルファベット以外
                        kigo_temp = kigo_temp & my_temp
                        han_temp = add_comma(han_temp)
                        kana_temp = add_comma(kana_temp)
                        num_temp = add_comma(num_temp)
                    End If
                                                                                       
                    str_temp = add_comma(str_temp)
                    hira_temp = add_comma(hira_temp)
                    zenkana_temp = add_comma(zenkana_temp)
                End If
            Next
            
            If set_text Like "* *" Or set_text Like "* *" Then
                Cells(i, space_cell).Value = "○"
            End If
            
            Cells(i, zenkaku_cell).Value = str_temp
            Cells(i, zenhira_cell).Value = hira_temp
            Cells(i, zenkana_cell).Value = zenkana_temp
            Cells(i, hankaku_cell).Value = han_temp
            Cells(i, hankana_cell).Value = kana_temp
            Cells(i, kigo_cell).Value = kigo_temp
            Cells(i, int_cell).Value = num_temp
            result = "混在"
            
        End If
        
        Cells(i, hantei_cell) = result

Continue:
    Next

End Sub

'分類分けで、続いている文字でなければカンマを挟むためのモジュール
Function add_comma(temp As Variant) As Variant
    
    If temp <> "" And Right(temp, 1) <> "," Then
        temp = temp & ","
    End If

    add_comma = temp
End Function

Tags: , , ,