Попробуйте это, надеюсь, это вам поможет.
blockquote><EditText android:id="@+id/xValue" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:hint="xValue" />
strtol
преобразует значение в long int
, диапазон которого может отличаться от int
. Кроме того, он возвращает LONG_MAX
или LONG_MIN
, если значение может быть преобразовано, но находится за пределами диапазона для long int
. В этом случае для errno
будет установлено значение ERANGE
(но не иначе!) Кроме того, в случае сбоя сопоставления возвращаемое значение равно 0, но errno
не установлено; но ep
указывает на начало строки.
int isInt (char *s)
{
char *ep = NULL;
// zero errno first!
errno = 0;
long i = strtol (s, &ep, 10);
if (errno) {
return 0;
}
// matching failure.
if (ep == s) {
return 0;
}
// garbage follows
if (! ((*ep == 0) || (!strcmp(ep,"\n")))) {
return 0;
}
// it is outside the range of `int`
if (i < INT_MIN || i > INT_MAX) {
return 0;
}
return 1;
}
То, что dbush говорит об использовании perror
, верно. strtol
устанавливает ошибку только в случае переполнения long
, что не является единственно возможным случаем сбоя в вашей функции, поэтому perror
может напечатать что-нибудь вроде Is a directory
или Multihop attempted
.
sscanf(buffer, any_format_without_width, &anytype);
недостаточно , недостаточно для обнаружения переполнения.
, если результат преобразования не может быть представлен в объекте, поведение не определено. C11dr §7.21.6.2 10
blockquote>Не используйте семейство
*scanf()
для обнаружения переполнения. Это может работать в некоторых случаях, но не в целом.
Вместо этого используйте функции
strto**()
. Тем не менее, даже ОПisInt()
неправильно закодированы, поскольку неправильно оцениваютisInt("\n")
,isInt("")
,isInt("999..various large values ...999")
как хорошиеint
с.Альтернатива:
bool isint_alt(const char *s) { char *endptr; errno = 0; long y = strtol(s, &endptr, 10); if (s == endptr) { return false; // No conversion } if (errno == ERANGE) { return false; // Outside long range } if (y < INT_MIN || y > INT_MAX) { return false; // Outside int range } // Ignore trailing white space while (isspace((unsigned char)*endptr)) { endptr++; } if (*endptr) { return false; // Trailing junk } return true; }
Если кто-то должен использовать sscanf()
для обнаружения переполнения int
, а не надежного strtol()
, существует громоздкий способ.
Используйте более широкий тип и ограничение ширины, чтобы предотвратить переполнение при сканировании.
bool isint_via_sscanf(const char *s) {
long long y;
int n = 0;
if (sscanf(s, "18%lld %n", &y, &n) != 1) { // Overflow not possible
return false; // Conversion failed
}
if (y < INT_MIN || y > INT_MAX) {
return false; // Outside int range
}
if (s[n]) {
return false; // Trailing junk
}
return true;
}
Недостаточно на редких платформах, где INT_MAX > 1e18
.
Также неверно возвращает ввод, такой как "lots of leading space and/or lot of leading zeros 000123"
, как недействительный.
Более сложный код, использующий sscanf()
, может устранить эти недостатки, но лучший подход - strto*()
.