2013-03-22 3 views
1

Проверка не должна использовать функции C++ 11 или дополнительные библиотеки, например. Boost, Regex и т. Д. Я придумал следующее решение. Ничего, кроме работы. Получается ли он более элегантным и/или быстрее отсюда?Быстрый способ определить, является ли строка номером JSON

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; 
} 

Прецедент небольшой встроенный сервер, который recieves огромные CSV файлов и anwsers клиентов с частями в формате JSON.

ответ

2

Это, вероятно, будет проще в использовании std::stod:

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

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

Если у вас нет std::stod, так как это функция С ++ 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, как хорошая функция для этого).

+0

Спецификация JSON описывает числа произвольного размера, которые могут превышать размер двойника. Также Infinity и NaN не являются допустимыми значениями для чисел, то же самое для гекса-десятичных чисел. также std :: stod is C++ 11 – aggsol

+0

Функция std :: strtod не подходит для проверки номера JSON. Спектр можно найти в RFC 4627. Версия OP (возможно) ОК. (Предполагая, что есть соответствующие модульные тесты;)) – CouchDeveloper

Смежные вопросы