问题
For my program I have to make sure the user only inputs a positive INTEGER. for example if the user inputted 12hi it should not run the program and print to std error. I am not quite sure how to implement this.
int main(int argc, char *argv[])
{
if(atoi(argv[1]) < 1)
{
cerr << "ERROR!"<< endl;
return 1;
}
return 0;
}
回答1:
Pass it to a std::istringstream and ensure all data was processed:
if (a_argc > 1)
{
std::istringstream in(a_argv[1]);
int i;
if (in >> i && in.eof())
{
std::cout << "Valid integer\n";
}
}
See online demo at http://ideone.com/8bEYJq.
回答2:
Ok, my revised answer. sscanf wasn't behaving how I thought it would and strtol provides the best C-like solution that is very portable.
#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;
}
Sample output: ./a.out 10 -1 32 1000 f -12347 +4 --10 10rubbish
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
This works because strtol will convert the argument to a long int. Then if end[0] is not at the end of the string it will be non-zero meaning it'll throw up an error for 10rubbish but be ok for values like 10. Then of course we only want positive integers and I've included the value 0 in that set.
atoi() by itself is not good enough as it returns zero for failure. 0 could be a valid input.
sscanf() also by itself is not good enough because it'll successfully convert strings like 10rubbish and return the value 10.
I realise op only wants argv[1], this answer scans through all provided args just to show the output of lots of valid and invalid entries.
回答3:
Since you evidently do not object to using the Standard C library, the function
long strtol (const char* str, char** endptr, int base)
from <cstdlib>
is quite sufficient to ensure that the
commandline argument is a (long) integer numeral with an optional
"-" or "+" prefix, and nothing more than that. You merely need to
check that the char *
stored at endptr
on return addresses '\0',
which tells you that the function has consumed the entire argument.
#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;
}
LATER ...or catering for Steve Jessop's comments:
#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;
}
A wrapper function would be in order for this degree of discrimination. And there
remains the very-very corner case that an input of ULONG_MAX
will be accepted
as LONG_MAX
.
回答4:
You can try checking if all the characters in argv[1]
are digits (possibly with a leading minus sign). The check can be performed by using the standard library function isdigit()
.
http://www.cplusplus.com/reference/cctype/isdigit/
Complete solution based on OP's actual code (also available at 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 );
}
回答5:
I'm new to C++ so please don't flame me if this is wrong, but couldn't you throw an exception and allow the user to re-correct the input?
I've learned a few ways of dealing with errors:
- If/Else handling
- Assert
- Throw exception
1.IF/ELSE #include
int main(int argc, int **argv) {
if (!isdigit(argv[1])) {
// handle code if it's not a digit.
return 0;
}
}
This is probably the easiest way to make sure
2.ASSERT #include
int main(int argc, int *argv[]) {
assert(isdigit(argv[1]));
}
* Assert will terminate the program if argv[1] is not a digit
3.THROW #include
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
}
}
It is definitely worth noting that throwing an exception will create a stack trace and also all code in-between the thrown exception and the block that catches the exception will NOT be executed.
来源:https://stackoverflow.com/questions/16156881/checking-to-make-sure-argv1-is-an-integer-c