Для моей программы я должен убедиться, что пользователь вводит только положительный INTEGER. например, если пользователь ввел 12hi, он не должен запускать программу и печатать в std error. Я не совсем уверен, как это реализовать.
int main(int argc, char *argv[])
{
if(atoi(argv[1]) < 1)
{
cerr << "ERROR!"<< endl;
return 1;
}
return 0;
}
Передай это 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.
Хорошо, мой пересмотренный ответ. 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], этот ответ просматривает все предоставленные аргументы, чтобы показать вывод множества допустимых и недействительных записей.
Поскольку вы, очевидно, не возражаете против использования стандартной библиотеки 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
,
Вы можете попробовать проверить, все ли символы в 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 );
}
Я новичок в C ++, поэтому, пожалуйста, не обращайте на меня внимания, если это не так, но не могли бы вы сгенерировать исключение и позволить пользователю повторно исправить ввод?
Я узнал несколько способов борьбы с ошибками:
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]));
}
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
}
}
Стоит отметить, что генерирование исключения создаст трассировку стека а также весь код между брошенным исключением и блоком, который перехватывает исключение, НЕ будет выполнен.