皆さんはいつもプログラミングで数値チェックをどのようにされていますか?

VBで数値チェックといえば、IsNumeric関数が有名ですが、単純にこれだけでは不十分なことが多く、意図しない不具合発生することもあります。
プログラミングでは、値のチェックはアプリケーションが正常に動作を続ける上で非常な重要な部分です。

.Netだと、Double.TryParseメソッド正規表現でチェックをされているのだと思います。しかし、私個人的な問題なのですが、正規表現は複雑になるとぱっと見わからなくなってきて体が受付ません^^;なので、IsNumeric後などにゴリゴリチェックロジックを書いています(という記事です)。

VB.NetだとMicrosoft.VisualBasic名前空間にあるIsNumericメソッドはつい便利なので使用してしまいがちです。単純にIsNumericだけのチェックで終わってはないでしょうか??

IsNumericの引数に
  • IsNumeric("123")の大文字
  • IsNumeric("10e3")の桁を表す文字
  • IsNumeric("&H12")の16進数を表す文字
も、Trueとして返ってきます。

これだと、その数値をそのままデータベースの決まったサイズに入れたりすると、エラーが発生することがあります。大文字だとコード体系のフィールドにしたい場合使えません。
やはり、IsNumeric関数(TryParseも同じ)の後に数字の範囲チェックや文字列チェックなどは欠かせないですね(>o<)

これがよい策かわかりませんが、私がよく使っている数値文字列チェックのロジックを晒しておきます。最後にC#バージョンあり。

数値文字列チェック

VB.Net

'/* <数値文字列チェック> */'
'/*  val…文字列 */'
'/*  len…最大整数部長さ。0の場合はチェックなし */'
'/*   inMinus…マイナスが含まれるか? */'
'/*   decimal_places…小数点以下の最大桁数 */'
Public Function CheckNum(val As String,
                       Optional len As UInteger = 0,
                       Optional inMinus As Boolean = False,
                       Optional decimal_places As UInteger = 0) As Boolean
   Dim wk_check_moji As String = "0123456789" '/* 許可する文字 */'

   '/* 普通の数値チェック(ここで大体除去) */'
   If IsNumeric(val) = False Then
      Return False
   End If

   '/* マイナス付き */'
   If inMinus = True Then
      wk_check_moji &= "-" '/* マイナス許可 */'
   End If

   '/* 桁数チェック */'
   If decimal_places > 0 Then '/* 小数桁があるか? */'
      Dim s() As String = val.Split("."c)
      If s.Length = 1 Then
         '/* 整数部分の長さチェック */'
         If len > 0 AndAlso s(0).Replace("-", "").Length > len Then
            Return False
         End If
      ElseIf s.Length = 2 Then '/* 小数点あり */'
         '/* 整数部分の長さチェック */'
         If len > 0 AndAlso s(0).Replace("-", "").Length > len Then
            Return False
         End If
         '/* 小数部分の長さチェック */'
         If decimal_places > 0 AndAlso s(1).Length > decimal_places Then
            Return False
         End If
         wk_check_moji &= "." '/* カンマ許可 */'
      Else
         '/* 小数点が複数の場合はエラー */'
         Return False
      End If
   Else
      '/* 整数部分の長さチェック */'
      If len > 0 AndAlso val.Replace("-", "").Length > len Then
         Return False
      End If
   End If

   '/* 禁則文字チェック */'
   For Each moji As Char In val
      If wk_check_moji.IndexOf(moji) < 0 Then
         '/* 文字が見つからない場合はエラー */'
         Return False
      End If
   Next
   Return True
End Function


C#

/* <数値文字列チェック> */
/*  val…文字列 */
/*  len…最大整数部長さ。0の場合はチェックなし */
/*   inMinus…マイナスが含まれるか? */
/*   decimal_places…小数点以下の最大桁数 */
public bool CheckNum(string val,
                       uint len,
                       bool inMinus,
                       uint decimal_places) {
    string wk_check_moji = "0123456789"; /* 許可する文字 */
    double wk_val;
    /* 普通の数値チェック(ここで大体除去) */
    if (double.TryParse(val,out wk_val) == false) {
        return false;
    }

    /* マイナス付き */
    if (inMinus == true) {
        wk_check_moji += "-"; /* マイナス許可 */
    }

    /* 桁数チェック */
    if (decimal_places > 0) { /* 小数桁があるか? */
        string[] sp = val.Split(new char[]{'.'});
        if (sp.Length == 1) {
            /* 整数部分の長さチェック */
            if (len > 0 && sp[0].Replace("-", "").Length > len) {
                return false;
            }
        } else if (sp.Length == 2) { /* 小数点あり */
            /* 整数部分の長さチェック */
            if (len > 0 && sp[0].Replace("-", "").Length > len) {
                return false;
            }
            /* 小数部分の長さチェック */
            if (decimal_places > 0 && sp[1].Length > decimal_places) {
                return false;
            }
            wk_check_moji += "."; /* カンマ許可 */
        } else {
            /* 小数点が複数の場合はエラー */
            return false;
        }
    } else {
        /* 整数部分の長さチェック */
        if (len > 0 && val.Replace("-", "").Length > len) {
            return false;
        }
    }

    /* 禁則文字チェック */
    foreach (char moji in val) {
        if (wk_check_moji.IndexOf(moji) < 0) {
            /* 文字が見つからない場合はエラー */
          return false;
       }
    }
    return true;
}


※このメソッドの後は、システムに合わせて数値の範囲チェックが必要です。

スポンサードリンク