J#(Java)指定した文字列に含まれる値を取得する (Val)

スポンサーリンク

ある文字列を数値に変換する場合は、不正な文字が入っている場合を考慮する必要があります。殆どのキャストでは、不正な文字が入っていると失敗します。(例外が発生する)

VB6 には Val という関数がありました。これは、数値として読み取り可能な部分のみを返すことができます。不正な文字ばかりの場合は、0 を返すことができるので、例外を考慮しなくて良いわけです。

VB.NET では Microsoft.VisualBasic 名前空間配下にある Val メソッドがこれにあたります。これまた、Microsoft.VisualBasic 名前空間配下を使いたくないという方のために自作してみました。指数の考慮があるため、ベタに組むほかありませんでした。8 進数、16 進数の対応は省きました。(言語によって表記方法が違うため)エラー検証でもあまり使う機会は少なくなりましたが、とりあえず紹介しておきます。

サンプルコード

以下にサンプルコードを示します。

J# 全般
import System.*;

/********************************************************************************
 *
 *      検証・エラーチェックをサポートした静的クラスです。
 *
 ********************************************************************************/

public final class Validation {

  #region Val メソッド (+2)

    /********************************************************************************
     *      指定した文字列に含まれる数値を変換して返します。
     *
     * @param   stTarget    任意の有効な文字列。
     * @return              指定した文字列に含まれる数値。
     ********************************************************************************/
    public static final double Val(final String stTarget) {
        // Null 値の場合は 0 を返す
        if (stTarget == null) {
            return 0D;
        }

        int iCurrent = 0;
        final int iLength = stTarget.get_Length();

        // 評価対象外の文字をスキップする
        for (iCurrent = 0; iCurrent < iLength; iCurrent++) {
            char chOne = stTarget.get_Chars(iCurrent);

            if ((chOne != ' ') && (chOne != ' ') && (chOne != '\t') && (chOne != '\n') && (chOne != '\r')) {
                break;
            }
        }

        // 終端までに有効な文字が見つからなかった場合は 0 を返す
        if (iCurrent >= iLength) {
            return 0D;
        }

        boolean bMinus = false;

        // 先頭にある符号を判定する
        switch (stTarget.get_Chars(iCurrent)) {
            case '-':
                bMinus = true;
                iCurrent++;
                break;
            case '+':
                iCurrent++;
                break;
        }

        int iValidLength = 0;
        int iPriod = 0;

        double dReturn = 0D;

        boolean bDecimal   = false;
        boolean bShisuMark = false;

        // 1 文字ずつ有効な文字かどうか判定する
        while (iCurrent < iLength) {
            char chCurrent = stTarget.get_Chars(iCurrent);

            if ((chCurrent == ' ') || (chCurrent == ' ') || (chCurrent == '\t') || (chCurrent == '\n') || (chCurrent == '\r')) {
                iCurrent++;
            } else if (chCurrent == '0') {
                iCurrent++;

                if ((iValidLength != 0) || bDecimal) {
                    iValidLength++;
                    dReturn = (dReturn * 10) + System.Double.Parse(System.Convert.ToString(chCurrent));
                }
            } else if ((chCurrent >= '1') && (chCurrent <= '9')) {
                iCurrent++;
                iValidLength++;
                dReturn = (dReturn * 10) + System.Double.Parse(System.Convert.ToString(chCurrent));
            } else if (chCurrent == '.') {
                iCurrent++;

                if (bDecimal) {
                    break;
                }

                bDecimal = true;
                iPriod = iValidLength;
            } else if ((chCurrent == 'e') || (chCurrent == 'E') || (chCurrent == 'd') || (chCurrent == 'D')) {
                bShisuMark = true;
                iCurrent++;
                break;
            } else {
                break;
            }
        }

        int iDecimal = 0;

        // 小数点が判定された場合
        if (bDecimal) {
            iDecimal = iValidLength - iPriod;
        }

        // 指数が判定された場合
        if (bShisuMark) {
            boolean bShisuValid = false;
            boolean bShisuMinus = false;
            double  dCoef = 0D;

            // 指数を検証する
            while (iCurrent < iLength) {
                char chCurrent = stTarget.get_Chars(iCurrent);

                if ((chCurrent == ' ') || (chCurrent == ' ') || (chCurrent == '\t') || (chCurrent == '\n') || (chCurrent == '\r')) {
                    iCurrent++;
                } else if ((chCurrent >= '0') && (chCurrent <= '9')) {
                    dCoef = (dCoef * 10) + System.Double.Parse(System.Convert.ToString(chCurrent));
                    iCurrent++;
                } else if (chCurrent == '+') {
                    if (bShisuValid) {
                        break;
                    }

                    bShisuValid = true;
                    iCurrent++;
                } else if ((chCurrent != '-') || bShisuValid) {
                    break;
                } else {
                    bShisuValid = true;
                    bShisuMinus = true;
                    iCurrent++;
                }
            }

            // 指数の符号に応じて累乗する
            if (bShisuMinus) {
                dCoef += iDecimal;
                dReturn *= System.Math.Pow(10, - dCoef);
            } else {
                dCoef -= iDecimal;
                dReturn *= System.Math.Pow(10, dCoef);
            }
        } else if (bDecimal && (iDecimal != 0)) {
            dReturn /= System.Math.Pow(10, iDecimal);
        }

        // 無限大の場合は 0 を返す
        if (System.Double.IsInfinity(dReturn)) {
            return 0D;
        }

        // マイナス判定の場合はマイナスで返す
        if (bMinus) {
            return -dReturn;
        }

        return dReturn;
    }

    /********************************************************************************
     *      指定した文字に含まれる数値を変換して返します。
     *
     * @param   chTarget    任意の有効な文字。
     * @return              指定した文字に含まれる数値。
     ********************************************************************************/
    public static final int Val(final char chTarget) {
        return (int)Val(System.Convert.ToString(chTarget));
    }

    /********************************************************************************
     *      指定したオブジェクトに含まれる数値を変換して返します。
     *
     * @param   oTarget 任意の有効なオブジェクト。
     * @return          指定したオブジェクトに含まれる数値。
     ********************************************************************************/
    public static final double Val(final Object oTarget) {
        if (oTarget != null) {
            return Val(oTarget.ToString());
        }

        return 0D;
    }

  #endregion

}

使用例は以下のようになります。

J# 全般
    // 不正な文字を含む文字列から数値部分のみを取得する
    double dValue = Validation.Val("  -10 24 [不正な文字] 512  ");

    MessageBox.Show(System.Convert.ToString(dValue)); //-1024

関連するリファレンス

準備中です。

スポンサーリンク