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;
}
}
Related
I have the following piece of simple code in the main() function.
Unfortunately, I cannot get main() to wcout the converted wchar_t array. Why is this so?
int main(int argc, wchar_t *argv[])
{
std::wcout << "first argument: " << std::wstring(argv[1])
}
this just prints
first argument:
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
In Java you can pass an argument with void main(String[] args).
Find run configuration in Eclipse, put arguments and run a program, but in C++ there is just int main() how to pass arguments to the program using Visual Studio 2010?
While int main() is correct, you can use int main(int argc, char *argv[]) or int main(int argc, char **argv) to get the argument count with argc and an array of char arrays (strings) with argv.
Please note that the first argument will always be the path to the program you are running.
It'you can refer to any basic c++ programs in any tutorial for this.
argc- number of argument count
argv- argumant list
Below is sample code to parse argument list.
#include <iomanip>
#include <iostream>
using namespace std;
int main( int argc, char* argv[] )
{
cout << "The name used to start the program: " << argv[ 0 ]
<< "\nArguments are:\n";
for (int n = 1; n < argc; n++)
cout << setw( 2 ) << n << ": " << argv[ n ] << '\n';
return 0;
}
If you are using visual studio there is a command line property using which you can pass commandline parms
Sample code :
// command_line_arguments.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
int main( int argc, // Number of strings in array argv
char *argv[], // Array of command-line argument strings
char *envp[] ) // Array of environment variable strings
{
int count;
// Display each command-line argument.
cout << "\nCommand-line arguments:\n";
for( count = 0; count < argc; count++ )
cout << " argv[" << count << "] "
<< argv[count] << "\n";
}
Read more about argument parsing in c++ read Parsing C++ Command-Line Arguments in MSDN. there are example input output also.
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.
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