How to convert command-line argument to int in C++ [duplicate] - c++

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
}

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.

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;
}

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;
}

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.

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

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;
}

Like that we can do....
int main(int argc, char *argv[]) {
int a, b, c;
*// Converting string type to integer type
// using function "atoi( argument)"*
a = atoi(argv[1]);
b = atoi(argv[2]);
c = atoi(argv[3]);
}

In my opinion this is the most practical way to pass your variables. Using std::stoi. It's good practice to use std:: and NOT to use namespace; this is why I can define a string with "string" as the variable name
#include <iostream>
#include <string>
int main(int argc, char **argv)
{
std::string string{argv[1]};
int integer1{std::stoi(argv[2])};
int integer2{std::stoi(argv[3])};
int sum{integer1 + integer2};
std::cout << string << " sum " << sum;
}
Example:
./out this 40 1 // input
this sum 41 // output

Related

C++ add checks to avoid reading two arguments

My code currently reads both arguments and i need to add a check for it to read 1 argument if someone put in one number such as 100 and to read the second argument if entered 100 3.
right now it reads both arguements everytime and and gives an error if one argument is entered.
#include <iostream>
#include <cstring>
using namespace std;
int perfectnumber(int number)
{
int sumofdivisor = 0;
for (int i = 1; i < number; i++)
{
if (number % i == 0)
sumofdivisor += i;
}
return abs(sumofdivisor - number);
}
int main(int argc, char *argv[])
{
int count = atoi(argv[2]);
int upper_limit = atoi(argv[1]);
for (int start = 2; start <= upper_limit; start++)
{
int difference = perfectnumber(start);
if (difference <= count)
{
cout << start << " ";
}
}
cout << endl;
}
The parameter argc is your friend, it tells you how many arguments there are.
Here is an example of how to use argc.
#include "stdio.h"
int main(int argc, char* argv[])
{
printf("Number: %d\n", argc);
printf("0: %s\n", argv[0]);
if (1<argc)
{
printf("1: %s\n", argv[1]);
}
}
You can use argc to see how many arguments are provided. The first argument is the name of the executable1, so you have to compare with 3. Here is a simple example:
#include <iostream>
#include <cstdlib>
int main(int argc, char *argv[])
{
if (argc < 3) {
std::cerr << "Too few arguments\n";
return EXIT_FAILURE;
}
std::cout << "Args: " << argv[1] << " and " << argv[2] << '\n';
}
1 This is not entirely correct. According to this reference: "argv[0] is the pointer to the initial character of a null-terminated multibyte string that represents the name used to invoke the program itself (or an empty string "" if this is not supported by the execution environment)." But as a comment points out, this is not entirely accurate either. This is a convention that implementations usually follow but are free to not to.

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

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;
}
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.
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.
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.
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 );
}
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:
If/Else handling
Assert
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.

How to output an integer value in command line argument to characters of the equivalent length as the value in C++?

I got a value say 10 and i want to output this into xxxxxxxxxx (10 x). How do i do this?
The value 10 is passed in via the command line.
I have tried this, but it doesn't do what I want:
for (i = 1; i < argc; i++){
cout << argv[i++] << " " << argv[i] << endl;
} // i cant get the argv[i] to print out the value in 'x'
if (argc>1)
cout << string(atoi(argv[1]), 'x');
There is a way using the streams, but I don't know it offhand: it's something like cout.SetPrecision(). But the C way is to provide a format specification.
int
main (int argc, char **argv)
{
printf ("%*d\n", atoi(argv[1]), 10); // outputs 10 into fieldwidth given by parameter
}
This needs quite a bit of development to handle pathologies of input, but the basic concept works. * means use the next parameter as a field width.
You simply need
std::cout << std::string(10, 'x');
So fullblown:
#include <iostream>
#include <string>
#include <sstream>
int main(int argc, const char* args[])
{
if (argc>1)
{
std::istringstream iss(args[1]);
unsigned long i = 0;
iss >> i;
std::cout << std::string(i, 'x');
}
return 0;
}
See here

convert string to integer in c++

Hello
I know it was asked many times but I hadn't found answer to my specific question.
I want to convert only string that contains only decimal numbers:
For example 256 is OK but 256a is not.
Could it be done without checking the string?
Thanks
The simplest way that makes error checking optional that I can think of is this:
char *endptr;
int x = strtol(str, &endptr, 0);
int error = (*endptr != '\0');
In C++ way, use stringstream:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
stringstream sstr;
int a = -1;
sstr << 256 << 'a';
sstr >> a;
if (sstr.failbit)
{
cout << "Either no character was extracted, or the character can't represent a proper value." << endl;
}
if (sstr.badbit)
{
cout << "Error on stream.\n";
}
cout << "Extracted number " << a << endl;
return 0;
}
An other way using c++ style : We check the number of digits to know if the string was valid or not :
#include <iostream>
#include <sstream>
#include <string>
#include <cmath>
int main(int argc,char* argv[]) {
std::string a("256");
std::istringstream buffer(a);
int number;
buffer >> number; // OK conversion is done !
// Let's now check if the string was valid !
// Quick way to compute number of digits
size_t num_of_digits = (size_t)floor( log10( abs( number ) ) ) + 1;
if (num_of_digits!=a.length()) {
std::cout << "Not a valid string !" << std::endl;
}
else {
std::cout << "Valid conversion to " << number << std::endl;
}
}

Parsing command line arguments in a unicode C++ application

How can I parse integers passed to an application as command line arguments if the app is unicode?
Unicode apps have a main like this:
int _tmain(int argc, _TCHAR* argv[])
argv[?] is a wchar_t*. That means i can't use atoi. How can I convert it to an integer? Is stringstream the best option?
if you have a TCHAR array or a pointer to the begin of it, you can use std::basic_istringstream to work with it:
std::basic_istringstream<_TCHAR> ss(argv[x]);
int number;
ss >> number;
Now, number is the converted number. This will work in ANSI mode (_TCHAR is typedef'ed to char) and in Unicode (_TCHAR is typedef`ed to wchar_t as you say) mode.
Dry coded and I don't develop on Windows, but using TCLAP, this should get you running with wide character argv values:
#include <iostream>
#ifdef WINDOWS
# define TCLAP_NAMESTARTSTRING "~~"
# define TCLAP_FLAGSTARTSTRING "/"
#endif
#include "tclap/CmdLine.h"
int main(int argc, _TCHAR *argv[]) {
int myInt = -1;
try {
TCLAP::ValueArg<int> intArg;
TCLAP::CmdLine cmd("this is a message", ' ', "0.99" );
cmd.add(intArg);
cmd.parse(argc, argv);
if (intArg.isSet())
myInt = intArg.getValue();
} catch (TCLAP::ArgException& e) {
std::cout << "ERROR: " << e.error() << " " << e.argId() << endl;
}
std::cout << "My Int: " << myInt << std::endl;
return 0;
}
A TCHAR is a character type which works for both ANSI and Unicode. Look in the MSDN documentation (I'm assuming you are on Windows), there are TCHAR equivalents for atoi and all the basic string functions (strcpy, strcmp etc.)
The TCHAR equivalient for atoi() is _ttoi(). So you could write this:
int value = _ttoi(argv[1]);
I personally would use stringstreams, here's some code to get you started:
#include <sstream>
#include <iostream>
using namespace std;
typedef basic_istringstream<_TCHAR> ITSS;
int _tmain(int argc, _TCHAR *argv[]) {
ITSS s(argv[0]);
int i = 0;
s >> i;
if (s) {
cout << "i + 1 = " << i + 1 << endl;
}
else {
cerr << "Bad argument - expected integer" << endl;
}
}