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

Как узнать, не сработала ли функция c atoi или была ли она нулей?

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

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

4b9b3361

Ответ 1

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

Возвращаемая функция преобразования строк в целые числа теперь stoi, которая принимает string и возвращает int, или генерирует исключение при ошибке.

Нет необходимости в подробном взломе istringstream, упомянутом в принятом ответе.

(Там также stol/stoll/stof/stod/stold для преобразований long/long long/float/double/long double соответственно.)

Ответ 2

Правильная функция (если вы настаиваете на использовании функций стиля 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 будет/может стать ненужной.

Ответ 3

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

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; 
}

Ответ 4

На странице man для strtol():

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

Ответ 5

Альтернативой 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 демонстрирует.

Ответ 6

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

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

if ( !value && string_number != "0" ) {
  // error
} else {
  // great success!
}