C ++ IsFloat функция - PullRequest
       84

C ++ IsFloat функция

24 голосов
/ 15 января 2009

Кто-нибудь знает удобный способ определения, является ли строковое значение «квалифицированным» как число с плавающей запятой?

bool IsFloat( string MyString )
{
   ... etc ...

   return ... // true if float; false otherwise
}

Ответы [ 15 ]

32 голосов
/ 15 января 2009

Если вы не можете использовать библиотечную функцию Boost, вы можете написать свою собственную функцию isFloat следующим образом.

#include <string>
#include <sstream>

bool isFloat( string myString ) {
    std::istringstream iss(myString);
    float f;
    iss >> noskipws >> f; // noskipws considers leading whitespace invalid
    // Check the entire string was consumed and if either failbit or badbit is set
    return iss.eof() && !iss.fail(); 
}
12 голосов
/ 15 января 2009

Вам может понравиться lexical_cast Boost (см. http://www.boost.org/doc/libs/1_37_0/libs/conversion/lexical_cast.htm).

bool isFloat(const std::string &someString)
{
  using boost::lexical_cast;
  using boost::bad_lexical_cast; 

  try
  {
    boost::lexical_cast<float>(someString);
  }
  catch (bad_lexical_cast &)
  {
    return false;
  }

  return true;
}

Вы можете использовать istream, чтобы избежать необходимости в Boost, но, честно говоря, Boost слишком хорош, чтобы его не использовать.

5 голосов
/ 03 ноября 2013

Вдохновленный этим ответом Я изменил функцию, чтобы проверить, является ли строка числом с плавающей запятой. Он не требует увеличения и не зависит от бит-потока строк - это просто разбор.

static bool isFloatNumber(const std::string& string){
    std::string::const_iterator it = string.begin();
    bool decimalPoint = false;
    int minSize = 0;
    if(string.size()>0 && (string[0] == '-' || string[0] == '+')){
      it++;
      minSize++;
    }
    while(it != string.end()){
      if(*it == '.'){
        if(!decimalPoint) decimalPoint = true;
        else break;
      }else if(!std::isdigit(*it) && ((*it!='f') || it+1 != string.end() || !decimalPoint)){
        break;
      }
      ++it;
    }
    return string.size()>minSize && it == string.end();
  }

* 1006 Т.е. *

1
2.
3.10000
4.2f
-5.3f
+6.2f

правильно распознается этой функцией как float.

1.0.0
2f
2.0f1

Примеры недопустимых операций с плавающей точкой. Если вы не хотите распознавать числа с плавающей запятой в формате X.XXf, просто удалите условие:

&& ((*it!='f') || it+1 != string.end() || !decimalPoint)

из строки 9. И если вы не хотите распознавать числа без «.» как float (то есть не '1', только '1.', '1.0', '1.0f' ...), тогда вы можете изменить последнюю строку на:

return string.size()>minSize && it == string.end() && decimalPoint;

Однако: есть много веских причин использовать lexical_cast для boost или решение, использующее stringstreams, а не эту «уродливую функцию». Но это дает мне больше контроля над тем, какие именно форматы я хочу распознавать как числа с плавающей запятой (т.е. максимальные цифры после десятичной запятой ...).

2 голосов
/ 23 мая 2018

Я недавно написал функцию для проверки, является ли строка числом или нет. Это число может быть целым или с плавающей точкой.

Вы можете крутить мой код и добавить несколько юнит-тестов.

bool isNumber(string s)
{
    std::size_t char_pos(0);

    // skip the whilespaces
    char_pos = s.find_first_not_of(' ');
    if (char_pos == s.size()) return false;


    // check the significand
    if (s[char_pos] == '+' || s[char_pos] == '-') ++char_pos; // skip the sign if exist

    int n_nm, n_pt;
    for (n_nm = 0, n_pt = 0; std::isdigit(s[char_pos]) || s[char_pos] == '.'; ++char_pos) {
        s[char_pos] == '.' ? ++n_pt : ++n_nm;
    }
    if (n_pt>1 || n_nm<1) // no more than one point, at least one digit
        return false;

    // skip the trailing whitespaces
    while (s[char_pos] == ' ') {
        ++ char_pos;
    }

    return char_pos == s.size();  // must reach the ending 0 of the string
}


void UnitTest() {
    double num = std::stod("825FB7FC8CAF4342");
    string num_str = std::to_string(num);

    // Not number
    assert(!isNumber("1a23"));
    assert(!isNumber("3.7.1"));
    assert(!isNumber("825FB7FC8CAF4342"));
    assert(!isNumber(" + 23.24"));
    assert(!isNumber(" - 23.24"));

    // Is number
    assert(isNumber("123"));
    assert(isNumber("3.7"));
    assert(isNumber("+23.7"));
    assert(isNumber("  -423.789"));
    assert(isNumber("  -423.789    "));
}
2 голосов
/ 15 января 2009

[РЕДАКТИРОВАТЬ: Исправлено, чтобы запретить начальные пробелы и завершающий ерунды.]

#include <sstream>

bool isFloat(string s) {
    istringstream iss(s);
    float dummy;
    iss >> noskipws >> dummy;
    return iss && iss.eof();     // Result converted to bool
}

Вы можете легко превратить это в функцию, настроенную для типа T вместо float. По сути, это то, что делает Boost's lexical_cast .

2 голосов
/ 15 января 2009

Я предполагаю, что вы захотите выполнить совпадение с регулярным выражением для входной строки. Я думаю, что может быть довольно сложно протестировать все крайние случаи.

На этом сайте есть хорошая информация. Если вы просто хотите пропустить до конца, он говорит: ^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$

Что в принципе имеет смысл, если вы понимаете синтаксис регулярных выражений.

1 голос
/ 26 мая 2019

Я искал нечто подобное, нашел гораздо более простой ответ, чем любой, который я видел;

bool is_float(float val){
    if(val != floor(val)){
        return true;
    }
    else
        return false;
}

или

auto lambda_isFloat = [](float val) {return (val != floor(val)); };

Надеюсь, это поможет!

ZMazz

1 голос
/ 20 марта 2015

C ++ 11 решение с использованием std::stof:

bool isFloat(const std::string& s) {
    try {
        std::stof(s);
        return true;
    } catch(...) {
        return false;
    }
}
1 голос
/ 16 января 2009

Вы можете использовать методы, описанные в Как я могу преобразовать строку в double в C ++? , и вместо броска conversion_error, вернуть false (указывая, что строка не представляет float) и true в противном случае.

0 голосов
/ 06 октября 2018
int isFloat(char *s){
  if(*s == '-' || *s == '+'){
    if(!isdigit(*++s)) return 0;
  }
  if(!isdigit(*s)){return 0;}
  while(isdigit(*s)) s++;
  if(*s == '.'){
    if(!isdigit(*++s)) return 0;
  }
  while(isdigit(*s)) s++;
  if(*s == 'e' || *s == 'E'){
    s++;
    if(*s == '+' || *s == '-'){
        s++;
        if(!isdigit(*s)) return 0;
    }else if(!isdigit(*s)){
        return 0;
    }
  }
  while(isdigit(*s)) s++;
  if(*s == '\0') return 1;
  return 0;
}
...