Checking to make sure argv[1] is an integer c++ - 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.
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.
Why do I get an Segmentation fault error
My code works fine on codeblocks compiler on my computer but when I upload it to an online editor I get an Segmentation fault error and I don't know why. #include <iostream> #include <string.h> #include <stdlib.h> #include <fstream> using namespace std; int main(int argc, char *argv[]) { ifstream stream(argv[1]); char line[1000]; int x,last=-1; while (stream>>line) { x = atoi(strtok(line,",")); cout<<x; last=x; while(x=atoi(strtok(NULL,","))) { if(x!=last) { cout<<","<<x; last=x; } } cout<<endl; } return 0; } You are given a sorted list of numbers with duplicates. Print out the sorted list with duplicates removed. And this is the input 6,7,8,9,9,10,11,12,13,14,15 11,12,13,14,15,16,17,18,19,20 2,2,2,2,2 10,11,12,13,14,15,16,16,17 13,14,14,15,16,17,17,17,18 15,16,17,17,18,18,18,18,19,19,20 2,3,4,5,5 13,14,15,16,17 10,11,12,13,14,15,15,15,15,16,16,16 12,13,14,15,16,17,17,18 5,6,7,8,9,10,11 14,14,14,15,15,16,17,17,18,19,19,20,21,22 13,14,15,16,16,17,17,18 15,16,17,18,19,20,21,21,21,21,22,22 6,6,6,7,8,9,10,11,11,11,12,12,13 12,12,13,14,15,15,16,17,17,18,19,19,20,21 8,9,9,9,10,10,11,12,13,13,14,15 12,13,14,15,16,17,18 1,1,1,2,2,3,3,4,4 1,2,3,4
Since you're asking us to guess, let's start at the top .... The code doesn't check that argv[1] is valid. If not, then you just dereferenced a null-pointer, and that caused your segmentation fault. Does your "online editor" pass parameters? I suggest checking argc > 1. Next, your code looks like it will pass a null pointer to atoi at the end of every line. That's another segmentation fault.
You are calling atoi with the result of strtok. If strtok doesn't find anything it returns a null pointer. This is the case at the end of the line. So you are passing a null pointer to atoi which then leads to a crash. Using your example this should work: #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string.h> #include <stdlib.h> #include <fstream> using namespace std; int main(int argc, char *argv[]) { ifstream stream(argv[1]); char line[1000]; char* ln; char* num; int x; int last; while (stream >> line) { ln = line; last = -1; while (num = strtok(ln, ",")) { x = atoi(num); if (x != last) { if(last != -1) cout << "," << x; else cout << x; last = x; } ln = NULL; } cout << endl; } return 0; } EDIT: Another solution with checking for valid paramters and w/o strtok and atoi: #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string.h> #include <stdlib.h> #include <fstream> using namespace std; int main(int argc, char *argv[]) { if (argc < 2) { cout << "Usage: " << argv[0] << " <file>"; return 1; } ifstream stream(argv[1]); if (!stream.is_open()) { cout << "Failed to open file \"" << argv[1] << "\""; return 2; } char line[1000]; while (stream >> line) { int last = -1; int x = 0; for (char* pos = line; pos < line + strlen(line); pos++) { if (*pos >= '0' && *pos <= '9') { x = (x * 10) + (*pos - '0'); } else { if (last != x) { if (last != -1) { cout << ','; } cout << x; last = x; } x = 0; } } cout << endl; } return 0; }
How to convert command-line argument to int in C++ [duplicate]
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
Modify contents of string literal C++ based on function constraints
I need to convert a given string literal to its lower case by passing the string as an argument to the function Lower(char *). The function can return only int. In the main() i need the converted string to be accessible somehow. Currently i am type casting the address of the tmp string in the Lower() function and then trying to dereference that address. This is the code: #include <stdio.h> #include <string.h> #include <ctype.h> int Lower(char* str) { char tmp[100]; for(int i=0;i<=strlen(str);i++) { if(isupper(*(str+i))) *(tmp+i) = *(str+i)+32; else *(tmp+i) = *(str+i); } return int(tmp); } int main() { char* str = "gOAt"; char *rc=(char *)Lower(str); printf(rc); return 0; } Again the function prototype cannot change ie the prototype must be int Lower(char *). However, "goat" must be somehow accessible in the main() function. How can this be done?
There are multiple things wrong with the posted code. My take would be that the int returned from the function is a status code, when it's 1, it signals that the conversion to lowercase was successful, 0 otherwise. Here is a working program that does the conversion: #include <iostream> using namespace std; int lower(char* str) { int hasLower = 0; while(*str) { if (*str >= 'A' && *str <= 'Z') { *str = (*str - 'A') + 'a'; hasLower = 1; } str++; } return hasLower; } int main(int argc, char** argv) { if (argc != 2) { cout << "No input! Exiting..." << endl; return 1; } char* input = argv[1]; if (lower(input)) { cout << "Lower case: " << input << endl; } else { cout << input << " isn't a valid string for lower-case conversion" << endl; } return 0; }
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