Преобразуйте строку в int в C ++ и проверка прошла успешно

Возможный дубликат:
преобразовать строку в int C ++
Какой самый быстрый способ проверить, является ли строка числом?

Мне нужно преобразовать строку в int, и мне нужно знать, было ли преобразование успешным. Но число может быть нулевым, поэтому я не могу использовать atoi и другие. Строка для преобразования, которую я прочитал из файла.


person Alecs    schedule 11.12.2012    source источник
comment
@chris не дублируется, в этом потоке только один ответ показывает, как проверить, было ли преобразование успешным, и сделал это для использования библиотеки boost, что для меня слишком много, чтобы использовать boost для одной проверки.   -  person Alecs    schedule 11.12.2012
comment
Например, std::stoi (также в ответах) выдает исключение, если что-то пойдет не так, но все равно принимает такие вещи, как 123abc, возвращая только 123 в качестве ответа. lexical_cast запрещает 123abc, но принимает строки с пробелами, преобразовывая только первое слово. Если вы хотите, чтобы он был более детализированным, вы можете создать собственную версию строкового потока. Конечно, всегда есть старый добрый strtol.   -  person chris    schedule 11.12.2012


Ответы (3)


вы можете использовать эту функцию-шаблон, но она предназначена не только для преобразования строки в int - она ​​предназначена для преобразования строки в каждый тип:

template <typename T>
T ConvertString( const std::string &data )
{
  if( !data.empty( ))
  {
    T ret;
    std::istringstream iss( data );
    if( data.find( "0x" ) != std::string::npos )
    {
      iss >> std::hex >> ret;
    }
    else
    {
      iss >> std::dec >> ret;
    }

    if( iss.fail( ))
    {
      std::cout << "Convert error: cannot convert string '" << data << "' to value" << std::endl;
      return T( );
    }
    return ret;
  }
  return T( );
}

Если вы хотите сейчас, если преобразование было успешным, то верните конкретное значение в if iss.fail() или передайте второй ссылочный аргумент функции и установите значение false, если оно не удалось.

Вы можете использовать это так:

uint16_t my_int = ConvertString<uint16_t>("15");

Если вам нравится решение со ссылочным аргументом, вот пример:

#include <iostream>
#include <sstream>
#include <string>

#include <inttypes.h>

template <typename T>
T ConvertString(const std::string &data, bool &success)
{
  success = true;
  if(!data.empty())
  {
    T ret;
    std::istringstream iss(data);
    if(data.find("0x") != std::string::npos)
    {
      iss >> std::hex >> ret;
    }
    else
    {
      iss >> std::dec >> ret;
    }

    if(iss.fail())
    {
      success = false;
      return T();
    }
    return ret;
  }
  return T();
}

int main(int argc, char **argv)
{
  bool convert_success;
  uint16_t bla = ConvertString<uint16_t>("15", convert_success);
  if(convert_success)
    std::cout << bla << std::endl;
  else
    std::cerr << "Could not convert" << std::endl;
  return 0;
}
person tuxtimo    schedule 11.12.2012
comment
Спасибо! Слишком сложно для моего случая, потому что мне нужно выполнить только одну проверку, но я использовал stringstream, потому что легко проверить, было ли преобразование успешным. - person Alecs; 11.12.2012
comment
Хорошо, возможно, вы сможете использовать этот метод в будущем для других случаев. Но да, в строковом потоке вы также можете использовать метод отказа, чтобы проверить, все ли было прочитано правильно. Спасибо, что приняли ответ - person tuxtimo; 11.12.2012

Также доступен старый добрый strtol. В коде C ++ лучше всего использовать #include <cstdio> как std::strtol:

#include <cstdlib>

//...

std::string str;
char *endp;

// change base 10 below to 0 for handing of radix prefixes like 0x
long value = std::strtol(str.c_str(), &endp, 10); 

if (endp == str.c_str()) { 
    /* conversion failed completely, value is 0, */ 
    /* endp points to start of given string */ 
}
else if (*endp != 0) {
    /* got value, but entire string was not valid number, */ 
    /* endp points to first invalid character */ 
}
else {
    /* got value, entire string was numeric, */
    /* endp points to string terminating 0 */ 
}
person hyde    schedule 11.12.2012

использовать потоки (c ++):

std::string intString("123");

int result;
std::stringstream stream(intString);

if (stream >> result) {
    std::cout << result;
} else {
    std::cout << "there was an error parsing the string";
}
person Julien May    schedule 11.12.2012
comment
Первый был явно запрещен (по уважительной причине), а второй не дает советов, как проверять наличие ошибок. - person chris; 11.12.2012
comment
Оператор извлечения потока возвращает логическое значение в случае успеха. Должно быть if (stream >> result) ... else ... - person acraig5075; 11.12.2012