How to convert a command-line argument to int?
Solution 1
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; simplest, but will treat any invalid number as 0:
#include <cstdlib>
int x = atoi(argv[1]);
The C way with input checking:
#include <cstdlib>
errno = 0;
char *endptr;
long int x = strtol(argv[1], &endptr, 10);
if (endptr == argv[1]) {
std::cerr << "Invalid number: " << argv[1] << '\n';
} else if (*endptr) {
std::cerr << "Trailing characters after number: " << argv[1] << '\n';
} else if (errno == ERANGE) {
std::cerr << "Number out of range: " << argv[1] << '\n';
}
The C++ iostreams way with input checking:
#include <sstream>
std::istringstream ss(argv[1]);
int x;
if (!(ss >> x)) {
std::cerr << "Invalid number: " << argv[1] << '\n';
} else if (!ss.eof()) {
std::cerr << "Trailing characters after number: " << argv[1] << '\n';
}
Alternative C++ way since C++11:
#include <stdexcept>
#include <string>
std::string arg = argv[1];
try {
std::size_t pos;
int x = std::stoi(arg, &pos);
if (pos < arg.size()) {
std::cerr << "Trailing characters after number: " << arg << '\n';
}
} catch (std::invalid_argument const &ex) {
std::cerr << "Invalid number: " << arg << '\n';
} catch (std::out_of_range const &ex) {
std::cerr << "Number out of range: " << arg << '\n';
}
All four variants assume that argc >= 2
. All accept leading whitespace; check isspace(argv[1][0])
if you don't want that. All except atoi
reject trailing whitespace.
Solution 2
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;
}
Solution 3
std::stoi from string could also be used.
#include <string>
using namespace std;
int main (int argc, char** argv)
{
if (argc >= 2)
{
int val = stoi(argv[1]);
// ...
}
return 0;
}
Solution 4
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.
Solution 5
The approach with istringstream can be improved in order to check that no other characters have been inserted after the expected argument:
#include <sstream>
int main(int argc, char *argv[])
{
if (argc >= 2)
{
std::istringstream iss( argv[1] );
int val;
if ((iss >> val) && iss.eof()) // Check eofbit
{
// Conversion successful
}
}
return 0;
}
![nosedive25](https://i.stack.imgur.com/zQEaF.jpg?s=256&g=1)
nosedive25
I work mostly with Cocoa and Objective-C. For the past 7 years, between school work and other things I've managed to learn a few programming languages. I've also done some work in Java for the Ludum Dare game jam competition. As for the web I'm fairly good with PHP and HTML5.
Updated on July 05, 2022Comments
-
nosedive25 about 2 years
I need to get an 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 }
-
WhirlWind about 14 yearsI'd recommend against atoi: "The atoi() function has been deprecated by strtol() and should not be used in new code."
-
CB Bailey about 14 yearsHow 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 avoidatoi
to me. -
Admin about 14 years@WhirlWind Deprecated by whom?
-
WhirlWind about 14 years@Neil I don't see where... maybe it's just my particular standard library that deprecates it.
-
nosedive25 about 14 yearsOh opps that was my mistake. I originally had it that way but then started trying different things and forgot to change it back.
-
michelson about 14 years@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.
-
jaques-sam about 7 yearsYou forgot std:: in front of istreamstream
-
Keyur Padalia about 7 years@DrumM OP has
using namespace std;
in the question. -
jaques-sam about 7 yearsCorrect (even it is a bad habit) ;-)
-
NathanOliver almost 6 yearsWould you mind adding a
stoi
solution now that we have that? That would make this answer more complete. -
Keyur Padalia almost 6 years@NathanOliver Done, but untested. Feel free to edit!
-
NathanOliver almost 6 years@Thomas Thanks.
-
Alan Birtles almost 6 years@Thomas you need to check pos from
std::stoi
it only throws if none of the string can be parsed as a number, e.g.std::stoi("1zz")
doesn't throw and returns 1 which is probably not what you want when parsing command line arguments. -
Keyur Padalia almost 6 years@AlanBirtles Done (and the same for the
istringstream
approach).