Проблема с преобразованием строки в int в C ++ - PullRequest
2 голосов
/ 03 апреля 2011

У меня есть приложение, где я получаю vector<string>. Мне нужно перебрать каждый элемент вектора и посмотреть, является ли значение целочисленным.

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

Я пытался использовать atoi(vector[index].c_str()), но у меня проблема с ним. atoi возвращает целочисленное значение, если значение, содержащееся в строке, является целым числом. Если нет, то возвращается 0

Итак, рассмотрим следующее:

atoi("Shankar") = 0
atoi("0") = 0

и

atoi("123") = 123
atoi("123Shankar") = 123

Итак, как мне отличить показанные выше случаи? Если это не может быть достигнуто с помощью atoi, то каково альтернативное решение этой проблемы?

Пожалуйста, помогите.

EDIT

Я могу перебрать строку и посмотреть, является ли каждый символ целым числом, но это снижает производительность, поскольку для m строк со средним из n символов мне нужно проверить m X n раз, что делает его O (n ^ 2). ).

Есть ли лучший способ решить эту проблему?

EDIT2

К сожалению, я не могу использовать какую-либо стороннюю библиотеку для этого и просто использую STL

EDIT3

В моем приложении вектор не содержит отрицательных целых чисел, поэтому я рассматриваю решение Xeo, поскольку sstream не различает «123» и «123Shankar»

Спасибо всем за помощь.

Ответы [ 7 ]

5 голосов
/ 03 апреля 2011

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

bool IsDigit(char c){
  return '0' <= c && c <= '9';
}

bool IsInteger(std::string const& str){
  size_t i = 0;
  if(*str == '-') ++i;
  for( ; i < str.size(); ++i){
     if(!IsDigit(str[i]))
       return false;
  }
  // all chars are integers
  return true;
}

Изменить
atoi на самом деле больше ничего не делаетПосмотрите этот пример реализации:

int StrToInt(char const* str){
  int ret = 0, sign = 1;
  if(*str == '-'){
    sign = -1;
    ++str;
  }
  while(IsDigit(*str)){
    ret *= 10; // make room for the next digit
    ret += ((*str) - 0x30); // convert char to digit
    ++str;
  }
  return ret * sign;
}
3 голосов
/ 03 апреля 2011
std::string intStr("123");
std::string nonintStr("hello");
try {
    int i = boost::lexical_cast<int>(intStr); //OK
    int j = boost::lexical_cast<int>("nonintStr); //throws
}
catch (boost::bad_lexical_cast & e) {
}
3 голосов
/ 03 апреля 2011

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

if(sscanf(s, "%d", &i) == EOF){
    // error
}

или c ++:

string s = "111";
stringstream ss(s);
int i;  
if((s >> i).fail()){
     //error
}
3 голосов
/ 03 апреля 2011

Попробуйте использовать istringstream

int value;
std::istringstream iss(yourvector[i]);
if(iss >> value)
   std::cout<<"value is not null"<<std::endl;
2 голосов
/ 03 апреля 2011

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

Если вы найдете общий шаблон со своими строками - возможно, они всегда имеют форму [цифры] [буквы] - тогда вы могли бы сначала выполнить быструю проверку символа LAST строки, чтобы выйти раньше. Для схожих функций, где важна производительность, я сначала проверяю каждый угловой случай, а другой - прямо посередине, прежде чем перебирать все.

Вот пример:

bool IsStringValidInt( const std::string& str )
{
    if( str.size() == 0 )
        return false;

    if( !isdigit( str[str.size() - 1] ) ||
        !isdigit( str[str.size() / 2] ) )
        return false;

    size_t i = 0;
    if( str[i] == '-' )
        ++i;

    for( ; i < str.size(); ++i )
        if( !isdigit( str[i] ) )
            return false;

    return true;
}
1 голос
/ 03 апреля 2011

Правильный способ проверки с помощью sscanf() следующий:

int    val;
char   dummy;

if (sscanf(str, "%d%c", &val, &dummy) == 1) {
    ... // "val" contains the string's integer value
} else {
    ... // the string does not contain an integer
}

Важно то, что компонент %c в строке формата заставляет sscanf() сообщать, есть ли что-нибудь после конца бита, который может быть проанализирован как целое число.

1 голос
/ 03 апреля 2011

Один из способов - проверить каждый символ каждой строки, чтобы увидеть, является ли это цифрой (используя isdigit )

...