Click to See Complete Forum and Search --> : Simple question regarding command line argument


pipa
June 2nd, 2008, 05:08 PM
Hi All,

I am trying to run my code based on the command line argument.
Following is the partial code:

int main(int argc, char *argv[]){
std::cout<<"******************************"<<std::endl;
std::cout<<std::endl;
std::cout<<"Method is: "<<argv[1]<<std::endl; // prints command line argument
.........
..............
...................
}


I want to check if the user has mentioned any command line argument or not, one simple way is to check "argc".....but I just want to know how do we check it through "argv[1]". For example, if i write the following code:

if(argv[1]==''){ //empty character
std::cerr<<"Method Missing"<<std::endl;
exit(1);
}

It doesn't work, as compiler says empty character constant.
If I use the following:

if(argv[1]==""){ //string literal
std::cerr<<"Method Missing"<<std::endl;
exit(1);
}


Then the compiler warns me of: comparison with string literal results in unspecified behavior

Can you guys suggest me, what is the best way.

Thanks.

Lindley
June 2nd, 2008, 05:21 PM
It is meaningless to index argv at or beyond argc, so first check that.

Second, in this case it's pointless to check for the empty string here because argv is built from all *non*-empty strings on the command-line.

What you have to do is put in a particular option, like "-n", and check for that directly. If you get something else, your command line is corrupted and you throw an error.

pipa
June 2nd, 2008, 05:29 PM
Thanks.
You are right, its meaningless to to check argv beyond argc, as its not populated yet.
Now I am using the following code:

if(argc<2){
std::cerr<<"Method Missing"<<std::endl;
exit(1);
}
else if(argv[1]!="old" && argv[1]!="new"){
std::cerr<<"Not an appropriate Method, use - old or new"<<std::endl;
exit(1);

}


The compiler warns me that comparison with string literals is not safe. Is there any other way to do this comparison?
I want to make sure that the command line argument is either "new" or "old".

Thanks.

MrViggy
June 2nd, 2008, 05:42 PM
'argv' is an array of pointers to a character that is (usually) an array of characters. You cannot compare a pointer to a string literal, you need to use functions like strcmp (http://msdn.microsoft.com/en-us/library/e0z9k731.aspx) to compare them.
Viggy

pipa
June 2nd, 2008, 06:29 PM
'argv' is an array of pointers to a character that is (usually) an array of characters. You cannot compare a pointer to a string literal, you need to use functions like strcmp (http://msdn.microsoft.com/en-us/library/e0z9k731.aspx) to compare them.
Viggy

Thanks.
After using std::strcmp, the compiler doesn't give me warning messages. But still, the code is not doing what I am expecting it to do. Following is the new code:


int main(int argc, char *argv[]){
std::cout<<"argc: "<<argc<<" "<<"argv"<<" "<<argv[1]<<std::endl;
if(argc<2){
std::cerr<<"Method Missing"<<std::endl;
exit(1);
}
if(!std::strcmp(argv[1],"old") && !std::strcmp(argv[1],"new")){
std::cerr<<"Not an appropriate Method, use - old or new"<<std::endl;
exit(1);

}

std::cout<<"******************************"<<std::endl;
std::cout<<std::endl;
std::cout<<"Method is: "<<argv[1]<<std::endl
......................
..............
}


When I provide no argument, code is doing the right thing (printing out " method missing"). When I provide any other argument (old, new, ggg, jjj etc.), it NEVER go into the second "if" condition. Can anybody please lemme know where am I wrong?

Thnks

Hermit
June 2nd, 2008, 06:59 PM
Thanks.
After using std::strcmp, the compiler doesn't give me warning messages. But still, the code is not doing what I am expecting it to do. Following is the new code:


int main(int argc, char *argv[]){
std::cout<<"argc: "<<argc<<" "<<"argv"<<" "<<argv[1]<<std::endl;
if(argc<2){
std::cerr<<"Method Missing"<<std::endl;
exit(1);
}
if(!std::strcmp(argv[1],"old") && !std::strcmp(argv[1],"new")){
std::cerr<<"Not an appropriate Method, use - old or new"<<std::endl;
exit(1);

}

std::cout<<"******************************"<<std::endl;
std::cout<<std::endl;
std::cout<<"Method is: "<<argv[1]<<std::endl
......................
..............
}


When I provide no argument, code is doing the right thing (printing out " method missing"). When I provide any other argument (old, new, ggg, jjj etc.), it NEVER go into the second "if" condition. Can anybody please lemme know where am I wrong?

Thnks
Did you read the reference that MrViggy linked to? strcmp returns 0 if the strings are equal, and zero of course converts to boolean false. Try:

if(std::strcmp(argv[1],"old") != 0 && std::strcmp(argv[1],"new") != 0){
std::cerr<<"Not an appropriate Method, use - old or new"<<std::endl;
exit(1);
}


Also, don't use the exit function to end your program. Since you're in main anyway, just use a return statement.

TheCPUWizard
June 2nd, 2008, 07:49 PM
FYI....


int x;

(x) == (x != 0);
(!x) == (x == 0);

pipa
June 2nd, 2008, 08:27 PM
FYI....


int x;

(x) == (x != 0);
(!x) == (x == 0);


I am sorry, I may be slow. I didn't get what u r trying to say in the above.

TheCPUWizard
June 2nd, 2008, 08:30 PM
I am sorry, I may be slow. I didn't get what u r trying to say in the above.


Comparing to X is the exact same as comparing to (X != 0).
Comparint to !X is the exact same as comparing to (X==0).

Hermit
June 2nd, 2008, 08:36 PM
FYI....


int x;

(x) == (x != 0);
(!x) == (x == 0);


Goes without saying. In this case, I much prefer making an explicit comparison to 0. This allows you to use comparison operators in a way that directly reflects the way we think about string comparison, for example:

strcmp(str1, str2) == 0; // str1 is equal to str2
strcmp(str1, str2) != 0; // str1 does not equal str2
strcmp(str1, str2) < 0; // str1 is "less than" str2
strcmp(str1, str2) > 0; // str1 is "greater than" str2
strcmp(str1, str2) <= 0; // etc.
strcmp(str1, str2) >= 0; // etc.

pipa
June 2nd, 2008, 08:39 PM
Did you read the reference that MrViggy linked to? strcmp returns 0 if the strings are equal, and zero of course converts to boolean false. Try:

if(std::strcmp(argv[1],"old") != 0 && std::strcmp(argv[1],"new") != 0){
std::cerr<<"Not an appropriate Method, use - old or new"<<std::endl;
exit(1);
}


Also, don't use the exit function to end your program. Since you're in main anyway, just use a return statement.

Thanks for ur suggestions. It worked!!
I also changed exit to return. If we are in functions other than "main", should we always use exit? OR where should we use exit and where should we use return?

Thanks.

TheCPUWizard
June 2nd, 2008, 08:43 PM
Goes without saying.

For experienced people...yes...see the OP's reply.....


In this case, I much prefer making an explicit comparison to 0.

In many cases I do also....


if (strcmp(b,c))
{
if (strcmp(a,b)/strcmp(b,c) > 0) { .... }
}


(That actually does something useful.....)

pipa
June 2nd, 2008, 08:45 PM
Comparing to X is the exact same as comparing to (X != 0).
Comparint to !X is the exact same as comparing to (X==0).

Ok, I got it.
You were talking in reference to my use of ( !strcmp(X) ).
Thanks for explaining.

Hermit
June 2nd, 2008, 08:55 PM
Thanks for ur suggestions. It worked!!
I also changed exit to return. If we are in functions other than "main", should we always use exit? OR where should we use exit and where should we use return?

Thanks.
Under normal circumstances, functions will complete whatever work they have to do and return to the calling function, eventually leading back to main. This gets a bit more complicated in an event-based application, where you need to post a quit message to stop the event loop, but it is fundamentally the same.

If a function in your programs needs to abruptly stop what it's doing due to some exceptional circumstance, there is an aptly named C++ feature for that purpose: exceptions. There's a lot to know about exceptions and exception-safety, but for the purpose of answering your question, it suffices to say that this feature exists.

Using the exit function is a lazy way to stop a program in the absence of proper program structure.

Hermit
June 2nd, 2008, 09:13 PM
In many cases I do also....


if (strcmp(b,c))
{
if (strcmp(a,b)/strcmp(b,c) > 0) { .... }
}


(That actually does something useful.....)
I'm a little curious about this. Aren't the non-zero return values of strcmp unspecified? I can see how if you used multiplication it would be a sort of logical and (edit: only sort of), but division seems like it could round off to zero (imagine a strcmp implementation that returns the difference of the unequal characters).

TheCPUWizard
June 2nd, 2008, 09:27 PM
I'm a little curious about this. Aren't the non-zero return values of strcmp unspecified? I can see how if you used multiplication it would be a sort of logical and (edit: only sort of), but division seems like it could round off to zero (imagine a strcmp implementation that returns the difference of the unequal characters).

it is actually a VERY old teaser...

"Pretend" would could compare string values with "normal" operators. and use "regular" math....


if ((a<b<c) || (a>b>c)) {...}


A simple test to see if three strings are different and monotonically either increasing or decreasing.

All the division cares about is the sign. If they are poth the same it will be positive, if they are different they will be negative....

Hermit
June 2nd, 2008, 09:53 PM
it is actually a VERY old teaser...

"Pretend" would could compare string values with "normal" operators. and use "regular" math....


if ((a<b<c) || (a>b>c)) {...}


A simple test to see if three strings are different and monotonically either increasing or decreasing.

All the division cares about is the sign. If they are poth the same it will be positive, if they are different they will be negative....
Okay, that's what it looked like. I'm still curious about the use of division as opposed to multiplication. My thoughts on this are:

a) strcmp is specified as returning either 0 or... something else. Suppose strcmp(a,b) returned 1 and strcmp(b,c) returned 2. In that case, strcmp(a,b)/strcmp(b,c) would equal 0.

b) Integer multiplication is faster than division (Which is to say that division is not faster than multiplication... not trying to say there's a significant speed difference).

MrViggy
June 3rd, 2008, 11:55 AM
'strcmp' is supposed to return a negative number if "a < b", and a positive number if "a > b". In the comparison that TheCPUWizard posted, we only care if the result is negative or positive. Negative divided by negative results in a positive; negative divided by positive results in a negative. The actual value is irrelevant.

Viggy

Lindley
June 3rd, 2008, 12:25 PM
That's assuming it's always the *same* positive or negative value. If it isn't, Hermit is pointing out that integer division could cause the result to be 0.