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.


如果你想禁止INFINITYNAN或十六进制浮点值,它就像检查字符串中的第二个或第三个字符不是字母一样简单:

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

对于“更大”的数字,总是有std::stoldor std::strtold。但是,如果您想要任意大小的数字,那么要么像现在一样做,要么使用诸如GMP之类的库(mpf_set_str这似乎是一个很好的功能)。

于 2013-03-22T09:31:04.187 回答