Как определить, является ли строка числом с C ++? - PullRequest
106 голосов
/ 11 января 2011

У меня было немало проблем при попытке написать функцию, которая проверяет, является ли строка числом.Для игры, которую я пишу, мне просто нужно проверить, является ли строка из файла, который я читаю, числом или нет (я буду знать, является ли это параметром таким образом).Я написал нижеприведенную функцию, которая, по моему мнению, работала гладко (или я случайно отредактировал ее, чтобы остановить, или я шизофреник, или Windows шизофреник):

bool isParam (string line)
{
    if (isdigit(atoi(line.c_str())))
        return true;

    return false;
}

Ответы [ 30 ]

115 голосов
/ 11 января 2011

Самый эффективный способ - просто перебирать строку, пока не найдете нецифровый символ.Если есть какие-либо нецифровые символы, вы можете считать строку не цифрой.

bool is_number(const std::string& s)
{
    std::string::const_iterator it = s.begin();
    while (it != s.end() && std::isdigit(*it)) ++it;
    return !s.empty() && it == s.end();
}

Или, если вы хотите сделать это в C ++ 11:

bool is_number(const std::string& s)
{
    return !s.empty() && std::find_if(s.begin(), 
        s.end(), [](char c) { return !std::isdigit(c); }) == s.end();
}

Как указано в комментариях ниже, это работает только для натуральных чисел.Если вам нужно обнаружить отрицательные целые или дробные числа, вам следует использовать более надежное решение на основе библиотеки.Хотя добавление поддержки отрицательных целых чисел довольно тривиально.

74 голосов
/ 16 мая 2013

Зачем изобретать велосипед? Стандартная библиотека C (также доступна на C ++) имеет функцию, которая делает именно это:

char* p;
long converted = strtol(s, &p, 10);
if (*p) {
    // conversion failed because the input wasn't a number
}
else {
    // use converted
}

Если вы хотите работать с дробями или научными обозначениями, используйте вместо этого strtod (вы получите double результат).

Если вы хотите разрешить шестнадцатеричные и восьмеричные константы в стиле C / C ++ ("0xABC"), вместо этого укажите последний параметр 0.

Ваша функция может быть записана как

bool isParam(string line)
{
    char* p;
    strtol(line.c_str(), &p, 10);
    return *p == 0;
}
28 голосов
/ 11 января 2011

Вы можете сделать это C ++ способом с boost :: lexical_cast.Если вы действительно настаиваете на том, чтобы не использовать повышение, вы можете просто изучить, что он делает, и сделать это.Это довольно просто.

try 
{
  double x = boost::lexical_cast<double>(str); // double could be anything with >> operator.
}
catch(...) { oops, not a number }
22 голосов
/ 31 июля 2013

С компилятором C ++ 11 для неотрицательных целых чисел я бы использовал что-то вроде этого (обратите внимание на :: вместо std::):

bool is_number(const std::string &s) {
  return !s.empty() && std::all_of(s.begin(), s.end(), ::isdigit);
}

http://ideone.com/OjVJWh

15 голосов
/ 09 мая 2013

Я просто хотел добавить эту идею, которая использует итерацию, но какой-то другой код выполняет эту итерацию:

#include <string.h>

bool is_number(const std::string& s)
{
    return( strspn( s.c_str(), "-.0123456789" ) == s.size() );
}

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

Уберите '.'и '-', если допустимы целые положительные числа.

15 голосов
/ 11 января 2011

Я бы предложил подход на основе регулярных выражений.Полное соответствие регулярному выражению (например, использование boost :: regex ) с

-?[0-9]+([.][0-9]+)?

покажет, является ли строка числом или нет.Сюда входят положительные и отрицательные числа, целые и десятичные числа.

Другие варианты:

[0-9]+([.][0-9]+)?

(только положительные)

-?[0-9]+

(только целые)

[0-9]+

(только положительное целое число)

12 голосов
/ 16 мая 2013

С этим решением вы можете проверить все, от отрицательных до положительных чисел и даже чисел с плавающей запятой. При изменении типа num на целое число вы получите ошибку, если строка содержит точку.

#include<iostream>
#include<sstream>
using namespace std;


int main()
{
      string s;

      cin >> s;

      stringstream ss;
      ss << s;

      float num = 0;

      ss >> num;

      if(ss.good()) {
          cerr << "No Valid Number" << endl;
      }
      else if(num == 0 && s[0] != '0') {
          cerr << "No Valid Number" << endl;
      }
      else {
          cout << num<< endl;
      }             
}

Доказательство: Программа C ++

9 голосов
/ 02 февраля 2014

Вот еще один способ сделать это с помощью библиотеки <regex>:

bool is_integer(const std::string & s){
    return std::regex_match(s, std::regex("[(-|+)|][0-9]+"));
}
6 голосов
/ 26 декабря 2015

Я нашел следующий код, чтобы быть наиболее устойчивым (c ++ 11). Ловит целые числа и числа с плавающей точкой.

bool isNumber( std::string token )
{
    using namespace std;
    return std::regex_match( token, std::regex( ( "((\\+|-)?[[:digit:]]+)(\\.(([[:digit:]]+)?))?" ) ) );
}
5 голосов
/ 07 июня 2016

Попробуйте это:

isNumber(const std::string &str) {    
  return !str.empty() && str.find_first_not_of("0123456789") == string::npos;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...