1

このチェックでは、C++ 11 の機能や追加のライブラリ (Boost、Regex など) を使用してはなりません。次の解決策を思いつきました。きれいではありませんが、機能しています。ここからよりエレガントになったり、高速になったりしますか?

bool isJsonNumber(const std::string& text)
{
    if(text.empty()) return false;

    bool foundE = false;
    bool foundESign = false;
    bool leadingZero = false;
    bool lastIsDigit = false;
    bool foundDot = false;

    for(uint32_t i=0; i < text.length(); ++i)
    {
        const unsigned char c = text[i];

        lastIsDigit = false;
        const bool currIsNoDigit = (c < '0' || c > '9');

        if(i == 0)
        {
            if(currIsNoDigit && c != '-' ) return false;
            if(c == '0') leadingZero = true;
            if(c != '-') lastIsDigit = true;
        }
        else
        {
            if(leadingZero)
            {
                leadingZero = false;
                if(c != '.') return false;
                foundDot = true;
            }
            else if(c == '.')
            {
                if(foundDot) return false;
                foundDot = true;
            }
            else if(c == 'e' || c == 'E')
            {
                if(foundE) return false;
                foundE = true;
            }
            else if(foundE && !foundESign)
            {
                if(currIsNoDigit && c != '-' && c != '+') return false;
                if(c == '+' || c == '-')
                {
                    foundESign = true;
                }
                else
                {
                    lastIsDigit = true;
                }
            }
            else
            {
                foundESign = false;
                if(currIsNoDigit) return false;
                lastIsDigit = true;
            }
        }
    }

    if(lastIsDigit == false) return false;

    return true;
}

ユース ケースは、巨大な CSV ファイルを受信し、JSON の一部でクライアントをアンサーする小さな組み込みサーバーです。

4

1 に答える 1

2

おそらく使いやすいでしょうstd::stod

size_t endpos;
std::stod(text, &endpos);

if (endpos != text.length())
{
    // Not a number
}
else
{
    // A number
}

を持っていない場合std::stod、これは C++11 の機能であるため、 で同様のことを行うことができますstd::strtod


INFINITYまたはまたは 16 進浮動小数点値を許可しない場合NANは、文字列の 2 番目または 3 番目の文字が文字ではないことを確認するのと同じくらい簡単です。

if ((text.length() > 2 && std::isalpha(text[1])) ||
    (text.length() > 3 && std::isalpha(text[2])))
{
    // Not a number
}

「より大きな」数値の場合は、常にstd::stoldまたはstd::strtold. ただし、任意のサイズの数値が必要な場合は、現在行っているようにするか、GMPなどのライブラリを使用します(mpf_set_strこれには良い機能のようです)。

于 2013-03-22T09:31:04.187 に答える