检查不得使用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部分的anwsers客户端。
答案 0 :(得分: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
或NAN
或十六进制浮点值,就像检查字符串中的第二个或第三个字符不是字母一样简单:
if ((text.length() > 2 && std::isalpha(text[1])) ||
(text.length() > 3 && std::isalpha(text[2])))
{
// Not a number
}
对于“较大”的numnbers,总是std::stold
或std::strtold
。但是,如果您想要任意大小的数字,那么要么像现在这样做,要么使用像GMP这样的库(mpf_set_str
似乎是一个很好的函数)。