Checking to make sure argv[1] is an integer c++

断了今生、忘了曾经 提交于 2019-12-13 16:47:05

问题


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:

  1. If/Else handling
  2. Assert
  3. 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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!