0

i want to use an argument in the command line as an integer. I also want to use a try/catch block to check, if it is a correct input:

int i;
try{
    i=atoi(argv[1]);
}catch(int e){
    printf("error: need integer\n");
    return 0;
}

But atoi seems to accept other inputs like characters and symbols. How can i overcome this?

Thanks, dalvo

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
dalvo
  • 47
  • 2
  • 7

2 Answers2

3

Use stoi:

try {
  i = std::stoi("1234");
}    
catch (std::invalid_argument) {
  //error
}
erlc
  • 652
  • 1
  • 6
  • 11
  • Or `strtol` if you don't want to use exceptions. – Simple Jan 31 '14 at 10:39
  • this is lame, *very* lame. I thought this question was about C++. – Paul Evans Jan 31 '14 at 10:48
  • @PaulEvans what do you mean? This is a C++ answer. – Simple Jan 31 '14 at 10:50
  • @Simple This is olde-timey C at best (in fact it's much worse) . You aren't using C++ at all here, let alone to the full power it gives you to do something as simple as this. – Paul Evans Jan 31 '14 at 10:52
  • @PaulEvans `std::stoi` is a C++ function. How could a function in the C standard throw exceptions? – Simple Jan 31 '14 at 11:00
  • @Simple the C standard is a document, it doesn't throw exceptions or even run as a program. Moving swiftly on from that -- the C++ standard provides a rich set libraries such as `strstream` to handle these things, And then `boost` provides very C++ stuff like `lexical_cast` – Paul Evans Jan 31 '14 at 11:05
  • @PaulEvans are you being deliberately obtuse? I'm done here. Don't think I didn't see your deleted trolling and inflammatory comments. – Simple Jan 31 '14 at 11:14
  • @PaulEvans using `strstream` for simple atoi convertion is not sort of C++ style. It's some sort of masochism. – qwm Jan 31 '14 at 11:23
  • @qwm even tough `strstream` was long ago deprecated, not until `boost::lexical_cast` was "fixed" a few years ago, it was the *fastest* way to convert `const char *` to integral types. So if you don't have acces to `boost` (as the OP doesn't) it's the best C++ way. – Paul Evans Jan 31 '14 at 11:30
  • The _fastest_ way would be `for(i=1; i<=len; i++) { str[len-i] = (char) ((val % 10) + '0'); val/=10; } str[i-1] = '\0';`. I'm 99% certain no C++ library can beat that code in terms of efficiency. – Lundin Jan 31 '14 at 12:35
0

Just one more snippet that may help, using std::stringstream.

#include<iostream>
#include<sstream>
#include<algorithm>
#include<locale>

int main(int argc, char** argv){

    // it should be a double, but makes easier 
    // to show ideas above
    int i;

    std::stringstream sstr(argv[1]);

    bool is_all_digit = true;
    // i tried to use a std::all_of, but get stuck...
    // this for do the same job
    // keep in mind thar for double, exponencial, etc
    //   there should be more valid chars
    // If you use only sstr >> i, if argv is, for instance 
    //  '12345asdfg' it will consider 12345.
    for(char& c: sstr.str()){
        is_all_digit &= std::isdigit(c);  
    }

    if( is_all_digit && !(sstr >> i).fail() )
        std::cout << "i == " << i << std::endl;
    else
        std::cerr << "Could not convert " << argv[1] << " to 'int'" << std::endl;
    return 0;
}
wesley.mesquita
  • 795
  • 5
  • 12