Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if argv[count] is an integer

Tags:

c

pointers

printf

I'm trying to create a command line application in C++ and I want to make sure that the input is an integer after a certain command argument.

For this example, I want to check if the next argument is an integer after the "-p" command argument. Here's the snippet of my code right now.

while (count < argc){
    if (strcmp("-p", argv[count]) == 0){
        has_p = true; //Boolean
        pid = atoi(argv[count + 1]);
        if (pid == 0 && argv[count + 1] != "0" ){
            err = 1;
            cout << "pid argument is not a valid input" << endl;
            pid = -1;
        }
        count++;
    }
...
}

Now this code correctly catches the error in this inputs:

  • -p 1777
  • -p sss
  • -p sss17
  • -p [space] -U

but fails at this input format

  • -p 17sss

I tried to remedy this by trying to compare it using sprintf. Unfortunately supplying sprintf with the char array pointer only outputs 1 character in buffer2.

while (count < argc){
    if (strcmp("-p", argv[count]) == 0){
        has_p = true; //Boolean
        pid = atoi(argv[count + 1]);
        sprintf(buffer, "%d", pid);
        sprintf(buffer2, "%d", *argv[count + 1]);
        if (pid == 0 && argv[count + 1] != "0" || (buffer != buffer2) ){
            err = 1;
            cout << "pid argument is not a valid input" << endl;
            pid = -1;
        }
        count++;
    }
...
}

Is there a way to make sprintf read the whole char array? If not, is there a better solution for this apart from looping through the pointer until I hit "\0"

like image 418
MDuh Avatar asked May 20 '15 11:05

MDuh


2 Answers

atoi() cannot do what you want. You need to use strtol() to achieve this. It has much improved error checking capacity.

Signature:

long int strtol(const char *nptr, char **endptr, int base);

This function returns the converted integral number as a long int value, else zero value is returned. After the conversion, you can check the contents of endptr and decide upon that.

like image 154
Natasha Dutta Avatar answered Sep 30 '22 20:09

Natasha Dutta


The following is a convenient one-liner...

sscanf(argv[count + 1], "%d%*c", &n) == 1

...that will evaluate true if it was possible to read into the int n and there was no trailing character afterwards. The '*' in %*c suppresses assignment, so there's no need to pass a pointer to a dummy char variable. See scanf docs here.

like image 36
Tony Delroy Avatar answered Sep 30 '22 20:09

Tony Delroy