views:

186

answers:

4

Hello,

I have a small c++ program that needs to get and argument and convert it to an int. Here is my code so far:

#include <iostream>


using namespace std;
int main(int argc,int argvx[]) {
    int i=1;
    int answer = 23;
    int temp;

    // decode arguments
    if(argc < 2) {
        printf("You must provide at least one argument\n");
        exit(0);
    }

    // Convert it to an int here

}
+1  A: 

Take a look at strtol(), if you're using the C standard library.

WhirlWind
+5  A: 

Since this answer was somehow accepted and thus will appear at the top, although it's not the best, I've improved it based on the other answers and the comments.

The C way; easiest, but will treat any invalid number as 0:

#include <cstdlib>

int x = atoi(argv[1]);

The C way with input checking:

#include <cstdlib>

char *endptr;
long int x = strtol(argv[1], &endptr, 10);
if (!*argv[1] || **endptr)
    cerr << "Invalid number " << argv[1] << '\n';

The C++ way with input checking:

#include <sstream>

istringstream ss(argv[1]);
int x;
if (!(ss >> x))
    cerr << "Invalid number " << argv[1] << '\n';

All three variants assume that arcg >= 2.

Thomas
I'd recommend against atoi: "The atoi() function has been deprecated by strtol() and should not be used in new code."
WhirlWind
How about the fact that it's impossible to tell whether a conversion actually took place with `atoi`? This would seem a pretty good reason to avoid `atoi` to me.
Charles Bailey
@WhirlWind Deprecated by whom?
anon
@Neil quotation from my man page... let me look.
WhirlWind
@Neil I don't see where... maybe it's just my particular standard library that deprecates it.
WhirlWind
@WhirlWind: I wouldn't go so far as to call it deprecated Many people still use it when there is no need to check inputs. As for failure checking, the answer isn't checking for failures either.
D.Shawley
+6  A: 

Note that your main arguments are not correct. The standard form should be:

int main(int argc, char *argv[])

or equivalently:

int main(int argc, char **argv)

There are many ways to achieve the conversion. This is one approach:

#include <sstream>

int main(int argc, char *argv[])
{
    if (argc >= 2)
    {
        std::istringstream iss( argv[1] );
        int val;

        if (iss >> val)
        {
            // Conversion successful
        }
    }

    return 0;
}
Charles Bailey
Oh opps that was my mistake. I originally had it that way but then started trying different things and forgot to change it back.
happyCoding25
+1 For inclusion of if successful
David Relihan
+3  A: 

As WhirlWind has pointed out, the recommendations to use atoi aren't really very good. atoi has no way to indicate an error, so you get the same return from atoi("0"); as you do from atoi("abc");. The first is clearly meaningful, but the second is a clear error.

He also recommended strtol, which is perfectly fine, if a little bit clumsy. Another possibility would be to use sscanf, something like:

if (1==sscanf(argv[1], "%d", &temp))
    // successful conversion
else
    // couldn't convert input

note that strtol does give slightly more detailed results though -- in particular, if you got an argument like 123abc, the sscanf call would simply say it had converted a number (123), whereas strtol would not only tel you it had converted the number, but also a pointer to the a (i.e., the beginning of the part it could not convert to a number).

Since you're using C++, you could also consider using boost::lexical_cast. This is almost as simple to use as atoi, but also provides (roughly) the same level of detail in reporting errors as strtol. The biggest expense is that it can throw exceptions, so to use it your code has to be exception-safe. If you're writing C++, you should do that anyway, but it kind of forces the issue.

Jerry Coffin