Проверка того, что argv [1] является целочисленным переполнением стека

Для моей программы я должен убедиться, что пользователь вводит только положительный INTEGER. например, если пользователь ввел 12hi, он не должен запускать программу и печатать в std error. Я не совсем уверен, как это реализовать.

int main(int argc, char *argv[])
{
if(atoi(argv[1]) < 1)
{
cerr << "ERROR!"<< endl;
return 1;
}
return 0;
}

2

Решение

Передай это std::istringstream и убедитесь, что все данные были обработаны:

if (a_argc > 1)
{
std::istringstream in(a_argv[1]);
int i;
if (in >> i && in.eof())
{
std::cout << "Valid integer\n";
}
}

Посмотреть онлайн демо на http://ideone.com/8bEYJq.

4

Другие решения

Хорошо, мой пересмотренный ответ. sscanf вел себя не так, как я думал, и strtol предоставляет лучшее C-подобное решение, которое очень переносимо.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
for (int i=1; i < argc; i++){
char* end;
long val = strtol(argv[i], &end, 10);
if (argc >= 2 && !end[0] && val >= 0){
printf("%s is valid\n", argv[i]);
} else {
printf("%s is invalid\n", argv[i]);
}
}
return 0;
}

Образец вывода:
./a.out 10 -1 32 1000 f -12347 +4 — 10 10 руб.

10 is valid
-1 is valid
32 is valid
1000 is valid
f is invalid
-12347 is valid
+4 is invalid
--10 is invalid
10rubbish is invalid

Это работает, потому что strtol преобразует аргумент в long int. Тогда, если end [0] не находится в конце строки, он будет отличен от нуля, то есть он выдаст ошибку для 10rubbish, но будет в порядке для значений, подобных 10. Тогда, конечно, мы хотим только положительные целые числа, и я включил значение 0 в этом наборе.

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

sscanf () также сам по себе не достаточно хорош, потому что он успешно преобразует строки вроде 10rubbish и возвращает значение 10.

Я понимаю, что op хочет только argv [1], этот ответ просматривает все предоставленные аргументы, чтобы показать вывод множества допустимых и недействительных записей.

1

Поскольку вы, очевидно, не возражаете против использования стандартной библиотеки C,
функция

long strtol (const char* str, char** endptr, int base)

от <cstdlib> вполне достаточно, чтобы гарантировать, что
аргумент командной строки — это (длинное) целое число с необязательным
Префикс «-» или «+» и ничего более. Вам просто нужно
проверьте, что char * хранится в endptr на обратные адреса ‘\ 0’,
который говорит вам, что функция использовала весь аргумент.

#include <cstdlib>
#include <iostream>

using namespace std;

int main(int argc, char *argv[])
{
if (argc < 2) {
return 1;
}

char * endp;
long i = strtol(argv[1],&endp,10);
if (!*endp) {
cout << "The value of \"" << argv[1] << "\" is " << i << endl;
return 0;
}
cerr << "\"" << argv[1] << "\" is not an integer" << endl;
return 1;
}

ПОТОМ …или угощение комментариями Стива Джессопа:

#include <cstdlib>
#include <iostream>
#include <climits>

using namespace std;

int main(int argc, char *argv[])
{
if (argc < 2) {
return 1;
}

char * endp;
long i = strtol(argv[1],&endp,10);

if (*endp) {
cerr << "\"" << argv[1] << "\" is not an integer :(" << endl;
return 1;
}
if (endp == argv[1]) {
cerr << "Empty string passed :(" << endl;
return 1;
}
if (i < 0) {
cerr << "Negative " << i << " passed :(" << endl;
return 1;
}
if (i <= INT_MAX) {
cout << "Non-negative int " << i << " passed :)" << endl;
} else {
cout << "Non-negative long " << i << " passed :)" << endl;
}
return 0;

}

Функция обертки была бы для этой степени различения. И там
остается очень-очень угловым случаем, что вход ULONG_MAX будут приняты
как LONG_MAX,

1

Вы можете попробовать проверить, все ли символы в argv[1] являются цифрами (возможно, с ведущим знаком минус). Проверка может быть выполнена с использованием стандартной функции библиотеки isdigit(),

http://www.cplusplus.com/reference/cctype/isdigit/

Полное решение на основе фактического кода OP (также доступно на http://codepad.org/SUzcfZYp):

#include <stdio.h>          // printf()
#include <stdlib.h>         // atoi()
#include <ctype.h>          // isdigit()

int main(int argc, char *argv[])
{
if( argc != 2 ) {
return 0;
}

char * pWord = argv[ 1 ];
char c = 0;
for( int i = 0; c = pWord[ i ], c ; ++i ) {
if( ! isdigit( c ) ) {
return 0;
}
}

int argvNum = atoi( argv[ 1 ] );
printf( "argc = %d, argv[ 1 ] = %s, argvNum = %d\n",
argc, argv[ 1 ], argvNum );
}
0

Я новичок в C ++, поэтому, пожалуйста, не обращайте на меня внимания, если это не так, но не могли бы вы сгенерировать исключение и позволить пользователю повторно исправить ввод?

Я узнал несколько способов борьбы с ошибками:

  1. Если / Остальное обработка
  2. утверждать
  3. Бросить исключение

1.IF / ELSE
#включают

int main(int argc, int **argv) {
if (!isdigit(argv[1])) {
// handle code if it's not a digit.
return 0;
}
}

Это, наверное, самый простой способ убедиться,


2.ASSERT
#включают

int main(int argc, int *argv[]) {
assert(isdigit(argv[1]));
}

* Assert завершит программу, если argv [1] не является цифрой

3.THROW
#включают

using namespace std;

class Except {};

int main(int argc, int **argv) {
try {
isdigit(argv[1]);
throw Except();
// this code will not be executed
// if argv[1] is not a digit
}
catch (Except) {
cout << "argv[1] is not a digit.";
// handle exception or rethrow
}
}

Стоит отметить, что генерирование исключения создаст трассировку стека а также весь код между брошенным исключением и блоком, который перехватывает исключение, НЕ будет выполнен.

-1