Как проверить, чтобы убедиться, что у вас есть целое число перед вызовом atoi ()? - PullRequest
7 голосов
/ 03 октября 2010

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

Ответы [ 8 ]

21 голосов
/ 03 октября 2010

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

long int strtol(const char *nptr, char **endptr, int base);

Затем проверьте, если *endptr != nptr.Это означает, что строка, по крайней мере, начинается с целого числа.Вы также можете проверить, что * endptr указывает на завершающий ноль, что означает, что вся строка была успешно проанализирована.

5 голосов
/ 03 октября 2010

atoi() не будет (не должен) вызывать переполнение стека, если строка содержит символы, отличные от цифр.Он просто преобразует в int любую цифру, найденную в начале строки, до тех пор, пока ее больше не будет.

  int x = atoi("12monkeys"); // x is 12
  int y = atoi("monkeys12"); // y is 0

Вы можете проверить, что целочисленное переполнение (число вне диапазона [-2 ^ 31, 2 ^ 31-1] на современной (текущей) архитектуре ПК).

edit (комментарии)

Покастандарты C предупреждают о неопределенном поведении , если значение не может быть представлено, наиболее распространенные последние компиляторы C (gcc, MS ...) не аварийно завершают работу , если значение неприемлемо(если, конечно, указатель char * не является нулевым или неправильным).

В любом случае, вы можете легко реализовать свой собственный atoi() (с теми же ограничениями, что и в моем ответе)

    #include <ctype.h>

    int myatoi(char *s) {
       int res = 0, minus = *s == '-';
       if (minus) s++;

       while (isdigit(*s)) {
          res = res*10 + (*s++ - '0');
       }

       return minus ? -res : res;
    }
1 голос
/ 03 октября 2010

Вызывает переполнение стека? Ну, я полагаю, это один из возможных результатов неопределенного поведения , если значение в строке выходит за пределы диапазона int. На практике, однако, он обычно просто оборачивает или возвращает фиктивный результат.

Если вы хотите улучшить проверку ошибок, используйте strtol вместо atoi. Он имеет четко определенное поведение при переполнении (он устанавливает errno, который необходимо очистить до 0 перед вызовом strtol, чтобы вы могли различать возврат ошибок и допустимые возвращаемые значения), и вы можете проверить точку в строке который прервал преобразование, чтобы увидеть, является ли полная строка целым числом или есть дополнительный контент после конца.

1 голос
/ 03 октября 2010

Это не вызывает переполнение стека. atoi возвращает 0, если не может найти число в начале строки. Ваша (не) обработка 0 является причиной переполнения стека.

0 голосов
/ 08 августа 2016

atoi() преобразует строку в целое число, если она содержит только цифры, в противном случае возвращается 0.

0 голосов
/ 03 октября 2010

Либо вы можете сделать это и ввести Undefined Behavior land, вы можете написать простую функцию проверки, например, так:

/* returns 0 on success, 1 on failure. */

int verify(char * string)
{
    int x = 0;
    int len = strlen(string);

    while(x < len) {
           if(!isdigit(*(string+x)))
           return 1;

           ++x;
    }

    return 0;
}

Обратите внимание, что вам нужно вызвать эту функцию до вызовите atoi (), и вам понадобятся string.h и stdio.h.

0 голосов
/ 03 октября 2010

Это может помочь вам. Чек strtol доступен в stdlib.h

0 голосов
/ 03 октября 2010

Я не думаю, что стандартный atoi будет переполняться стеком, но нет никакого способа узнать, нет ли у вас целого числа с ним. Вместо этого используйте strtol - возможно иметь дело с нецелыми числами.

http://en.wikipedia.org/wiki/Strtol

...