Как я должен убедиться, что целочисленное значение, переданное из argv, не переполнится? - PullRequest
8 голосов
/ 01 апреля 2019

У меня есть программа, которая требует, чтобы пользователь вводил целое число в качестве аргумента командной строки, в виде ./program 100.

Очевидно, что это будет читать значение в виде строки, поэтому мне нужно проанализировать его в целое число. Я должен убедиться, что входное значение не будет переполнять целочисленную переменную. Я прочитал о strtol(), но он работает с long переменными, и я должен придерживаться обычного int.

Есть ли что-нибудь подобное, что можно использовать для int?

Ответы [ 2 ]

7 голосов
/ 01 апреля 2019

Вы можете использовать strtol для этого.Сначала вам нужно проверить, если эта функция не преобразует значение.Если преобразование выполнено успешно, проверьте, находится ли значение в диапазоне от INT_MIN до INT_MAX:

errno = 0;
long x = strtol(argv[1], NULL, 10);
if (errno) {
    perror("conversion failed");
} else if (x < INT_MIN) {
    printf("value too small\n");
} else if (x > INT_MAX) {
    printf("value too big\n");
} else {
    printf("value = %ld\n", x);
}

Обратите внимание, что это будет работать, если long имеет такой же размер, как int илибольше.

Если sizeof(long) > sizeof(int), проверки INT_MIN и INT_MAX будут обнаруживать случаи, когда значение соответствует long, но не int.Если sizeof(long) == sizeof(int), значение вне диапазона приведет к тому, что для errno будет установлено значение, отличное от нуля, чтобы поймать ошибку, а случаи INT_MIN и INT_MAX никогда не будут истинными.

1 голос
/ 02 апреля 2019

Как мне проверить, что целочисленное значение, переданное из argv, не переполнится?

Используйте strtol() и проверьте указатель конца. Затем проверьте errno и, возможно, тест диапазона

if (argc > 1) {
  char *endptr;
  errno = 0;
  long num = strtol(argv[1], &endptr, 10);

  if (argv[1] == endptr) {
    puts("No conversion");
  } else if (errno == ERANGE) {
    puts("Value outside long range");
  #if LONG_MIN < INT_MIN || LONG_MAX > INT_MAX
  } else if (num < INT_MAX || num > INT_MAX) {
    errno = ERANGE;
    puts("Value outside int range");
  #endif
  } else {
    // If code wants to look for trailing junk
    if (*endptr) {
      puts("Non-numeric text");
    } else {
      printf("Success %d\n", (int) num);
    } 
  } 

На основании Почему в stdlib.h нет strtoi?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...