Подтвердить что ты не робот

Как проверить, является ли строка С++ int?

Когда я использую getline, я бы ввел кучу строк или чисел, но я хочу, чтобы цикл while выводил "слово", если это не число. Так есть ли способ проверить, является ли "слово" числом или нет? Я знаю, что я мог бы использовать atoi() для C-строки, но как насчет строк строкового класса?

int main () {
  stringstream ss (stringstream::in | stringstream::out);
  string word;
  string str;
  getline(cin,str);
  ss<<str;
  while(ss>>word)
    {
      //if(    )
        cout<<word<<endl;
    }
}
4b9b3361

Ответ 1

Другая версия...

Используйте strtol, оборачивая его внутри простой функции, чтобы скрыть ее сложность:

inline bool isInteger(const std::string & s)
{
   if(s.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) return false;

   char * p;
   strtol(s.c_str(), &p, 10);

   return (*p == 0);
}

Почему strtol?

Насколько я люблю C++, иногда C API является лучшим ответом, насколько я понимаю:

  • использование исключений является излишним для теста, который разрешен на неудачу
  • создание объекта временного потока лексическим преобразованием является чрезмерным и неэффективным, когда стандартная библиотека C имеет малоизвестную выделенную функцию, которая выполняет эту работу.

Как это работает?

strtol первый взгляд strtol кажется довольно сырым, поэтому объяснение сделает код более простым для чтения:

strtol проанализирует строку, остановившись на первом strtol который нельзя считать частью целого числа. Если вы предоставите p (как я сделал выше), он устанавливает p прямо на этот первый нецелый символ.

Я считаю, что если p не установлен в конец строки (символ 0), то в строке s есть нецелый символ, означающий, что s не является правильным целым числом.

Первые тесты предназначены для устранения угловых случаев (начальные пробелы, пустая строка и т.д.).

Эта функция, конечно, должна быть настроена в соответствии с вашими потребностями (ли пробелы - ошибка? И т.д.).

Источники:

Смотрите описание strtol адресу: http://en.cppreference.com/w/cpp/string/byte/strtol.

См. Также описание родственных функций strtol (strtod, strtoul и т.д.).

Ответ 2

Принятый ответ даст ложный положительный результат, если ввод представляет собой число плюс текст, потому что "stol" преобразует первые цифры и игнорирует остальные.

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

#include <string>

...

std::string s;

bool has_only_digits = (s.find_first_not_of( "0123456789" ) == std::string::npos);

РЕДАКТИРОВАТЬ: если вам нравится эта реализация, но вы хотите использовать ее как функцию, то это должно сделать:

bool has_only_digits(const string s){
  return s.find_first_not_of( "0123456789" ) == string::npos;
}

Ответ 3

Вы можете попробовать boost::lexical_cast. Он выдает исключение bad_lexical_cast, если он терпит неудачу.

В вашем случае:

int number;
try
{
  number = boost::lexical_cast<int>(word);
}
catch(boost::bad_lexical_cast& e)
{
  std::cout << word << "isn't a number" << std::endl;
}

Ответ 4

Если вы просто проверяете, является ли word число, это не слишком сложно:

#include <ctype.h>

...

string word;
bool isNumber = true;
for(string::const_iterator k = word.begin(); k != word.end(); ++k)
    isNumber &&= isdigit(*k);

Оптимизируйте по желанию.

Ответ 5

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

Ответ 6

Используйте всемогущие функции C stdio/string:

int dummy_int;
int scan_value = std::sscanf( some_string.c_str(), "%d", &dummy_int);

if (scan_value == 0)
    // does not start with integer
else
    // starts with integer

Ответ 7

Хорошо, как я вижу, у вас есть 3 варианта.

1: Если вы просто хотите проверить, является ли число целым, и не заботятся о его преобразовании, но просто хотите сохранить его как строку и не заботиться о потенциальных переполнениях, проверяя, соответствует ли оно regex для целого числа будет идеальным здесь.

2: Вы можете использовать boost:: lexical_cast, а затем поймать исключение потенциального boost:: bad_lexical_cast, чтобы узнать, не произошло ли преобразование. Это будет хорошо работать, если вы можете использовать boost, и если отказ от преобразования является исключительным условием.

3: сворачивайте свою собственную функцию, аналогичную lexical_cast, которая проверяет преобразование и возвращает true/false в зависимости от того, успешна она или нет. Это будет работать в случае, если 1 и 2 не соответствуют вашим требованиям.

Ответ 8

template <typename T>
const T to(const string& sval)
{
        T val;
        stringstream ss;
        ss << sval;
        ss >> val;
        if(ss.fail())
                throw runtime_error((string)typeid(T).name() + " type wanted: " + sval);
        return val;
}

И тогда вы можете использовать его так:

double d = to<double>("4.3");

или

int i = to<int>("4123");

Ответ 9

Я изменил метод paercebal для удовлетворения моих потребностей:

typedef std::string String;    

bool isInt(const String& s, int base){
   if(s.empty() || std::isspace(s[0])) return false ;
   char * p ;
   strtol(s.c_str(), &p, base) ;
   return (*p == 0) ;
}


bool isPositiveInt(const String& s, int base){
   if(s.empty() || std::isspace(s[0]) || s[0]=='-') return false ;
   char * p ;
   strtol(s.c_str(), &p, base) ;
   return (*p == 0) ;
}


bool isNegativeInt(const String& s, int base){
   if(s.empty() || std::isspace(s[0]) || s[0]!='-') return false ;
   char * p ;
   strtol(s.c_str(), &p, base) ;
   return (*p == 0) ;
}

Примечание:

  • Вы можете проверить различные базы (двоичные, октавные, шестнадцатеричные и другие)
  • Сделайте уверенным, вы не передаете 1, отрицательное значение или значение >36 в качестве базы.
  • Если вы передадите 0 в качестве базы, он автоматически определит базу i.e для строки, начинающейся с 0x, будет обрабатываться как hex, а строка, начинающаяся с 0, будет обрабатываться как oct. Символы не чувствительны к регистру.
  • Любое пустое пространство в строке приведет к возврату false.

Ответ 10

Вот еще одно решение.

try
{
  (void) std::stoi(myString); //cast to void to ignore the return value   
  //Success! myString contained an integer
} 
catch (const std::logic_error &e)
{   
  //Failure! myString did not contain an integer
}