Как мне определить, произошла ли ошибка функции c atoi или это была строка нулей?

StackOverflow https://stackoverflow.com/questions/1640720

  •  08-07-2019
  •  | 
  •  

Вопрос

При использовании функции atoi (или strtol или аналогичные функции, если на то пошло), как вы можете определить, не удалось ли целочисленное преобразование или преобразуемая C-строка была 0?

За то, что я делаю, 0 является приемлемым значением, и преобразуемая C-строка может содержать любое количество 0s.Он также может содержать начальный пробел.

Это было полезно?

Решение

Для C ++ 11 и более поздних версий:

Функция перехода для преобразования строки в целое теперь stoi , который принимает строку и возвращает int , либо выдает исключение при ошибке.

Больше нет необходимости в подробном хаке istringstream , упомянутом в принятом ответе.

(есть также stol / stoll / stof / stod / stold для long / long long / float / double / long double , соответственно .)

Другие советы

Правильной функцией (до тех пор, пока вы настаиваете на использовании функций в стиле C) является strtol и код преобразования может выглядеть следующим образом

const char *number = "10"; /* for example */

char *end;
long value = strtol(number, &end, 10); 
if (end == number || *end != '\0' || errno == ERANGE)
  /* ERROR, abort */;

/* Success */
/* Add whatever range checks you want to have on the value of `value` */

Некоторые замечания:

strtol позволяет (имеется в виду:незаметно пропускает) пробел перед фактическим числом.Если вы считаете, что такой начальный пробел является ошибкой, вы должны проверить это самостоятельно.

Проверка на *end != '\0' следит за тем, чтобы после цифр ничего не было.Если вы хотите разрешить использование других символов после фактического числа (пробел?), эта проверка должна быть изменена соответствующим образом.

P.S.Я добавил следующее end == number проверьте позже, чтобы перехватить пустые входные последовательности.Входные данные "Все пробелы" и "вообще никакого числа" были бы перехвачены *end != '\0' проверяйте в одиночку.Однако, возможно, имеет смысл заранее перехватить пустой ввод.В таком случае end == number проверка будет / может стать ненужной.

Поскольку этот тег помечен :

template< typename T >
inline T convert(const std::string& str)
{
    std::istringstream iss(str);
    T obj;

    iss >> std::ws >> obj >> std::ws;

    if(!iss.eof())
        throw "dammit!";

    return obj; 
}

Со страницы руководства для strtol ():

  

Если endptr не равен NULL, strtol () сохраняет адрес первого недействительного        символ в * endptr. Однако, если цифр не было вообще, strtol ()        сохраняет исходное значение nptr в * endptr. (Таким образом, если * nptr не         '\ 0' но ** endptr равен '\ 0' при возврате, вся строка была действительной.)

Альтернативой strtol является sscanf , хотя он немного тяжелый:

const char *numStr = "12345";  // input string
int value;
if(sscanf(numStr, "%d", &value) == 1)
    ;  // parsing succeeded, use value
else
    ;  // error

Однако это позволяет использовать пробел в начале строки (что может или не может быть желательно), и позволяет чему-либо следовать за числом, поэтому " 123abc " будет принят и возвращен 123. Если вы хотите иметь более жесткий контроль, используйте strtol () , как AndreyT демонстрирует .

Прошло много времени с тех пор, как я написал C / C ++, но мне кажется, что (слишком) простым решением было бы проверить только строку на наличие "0".

int value = atoi(string_number.c_str());

if ( !value && string_number != "0" ) {
  // error
} else {
  // great success!
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top