views:

3884

answers:

5

I'm trying to compare a character array against a string like so:

const char *var1 = " ";
var1 = getenv("myEnvVar");

if(var1 == "dev")
{
   // do stuff
}

This if statement never validates as true... when I output var1 it is "dev", I was thinking maybe it has something to do with a null terminated string, but the strlen of "dev" and var1 are equal... I also thought maybe var1 == "dev" was comparing "dev" against the memory location of var1 instead of the value. *var1 == "dev" results in an error.... tried many things, probably a simple solution for the saavy c++ developer (I havent coded c++ in a looong time).

edit: we've tried

if(strcmp(var1, "dev") == 0)

and

if(strncmp(var1, "dev", 3) == 0)

Thanks

edit: After testing at home I'm just going to suggest my co-worker changes the datatype to a string. I believe he was comparing a char array of a large size against a string. I put together a program that outputs sizeof, strlen, etc to help us work through it. Thanks to everyone for the help.

+14  A: 

Use strcmp() to compare the contents of strings:

if (strcmp(var1, "dev") == 0) {
}

Explanation: in C, a string is a pointer to a memory location which contains bytes. Comparing a char* to a char* using the equality operator won't work as expected, because you are comparing the memory locations of the strings rather than their byte contents. A function such as strcmp() will iterate through both strings, checking their bytes to see if they are equal. strcmp() will return 0 if they are equal, and a non-zero value if they differ. For more details, see the manpage.

John Millikin
We've tried that as well and it didnt work unfortunately
Chris Klepeis
@Chris: could you post an example of how you're using `strcmp()`? Otherwise, we won't know how it "didn't work".
John Millikin
Are you sure you didn't do if(strcmp(var1, "dev"))? An easy trap to fall into with strcmp...
Martin B
@chris additionally, is var1 null-terminated? (i.e. is the code sample 100% accurate, or are you using null-terminated "" strings for a quick explanation)
San Jacinto
I'm the eyes on this project, I don't have c++ on my work system to test so I'll test when I get home and post what I find out.
Chris Klepeis
A: 

In this code you are not comparing string values, you are comparing pointer values. If you want to compare string values you need to use a string comparison function such as strcmp.

if ( 0 == strcmp(var1, "dev")) {
  ..
}
JaredPar
Ohhh. I hate putting the 0 on the left (Personal opinion obviously). I think it is more intuative on the right and since you are testing the result against a function no chance of assignment.
Martin York
I call this "Yoda Coding" (backwards is the expression, hmmm?). I'd prefer to use compile options to catch accidental assignments.
Fred Larson
@Fred agree with you i do not. :)
JaredPar
A: 

Always test first:

const char * p= getenv("myEnvVar") ;
const char * q= "var" ;

printf(" >> comparing getenv [%s] against [%s]\n", p, q) ;
while ( * p && ( * p == * q )) { p ++, q ++ ; }   // basically strcmp
if ( * p ) {
  printf("failed at the letter '%c' (0x%02x)\n", * p, * p) ;
}
else {
  printf("They are equal.\n") ;
}
woolstar
Neraly correct. What if q is longer than p?
Martin York
Though this approach can work very well, since the nineties it has been put in a library. Better not rewrite strcmp (we probably suck at it). And if you want to, use std::mismatch.
xtofl
If q is longer, you would get the cryptic "failed at the letter '" :)And I unrolled strcmp() so I could print where the comparison failed at.
woolstar
A: 

"dev" is not a string it is a const char * like var1. Thus you are indeed comparing the memory adresses. Being that var1 is a char pointer, *var1 is a single char (the first character of the pointed to character sequence to be precise). You can't compare a char against a char pointer, which is why that did not work.

Being that this is tagged as c++, it would be sensible to use std::string instead of char pointers, which would make == work as expected. (You would just need to do const std::string var1 instead of const char *var1.

sepp2k
+4  A: 

You're not working with strings. You're working with pointers. var1 is a char pointer (const char*). It is not a string. If it is null-terminated, then certain C functions will treat it as a string, but it is fundamentally just a pointer.

So when you compare it to a char array, the array decays to a pointer as well, and the compiler then tries to find an operator == (const char*, const char*).

Such an operator does exist. It takes two pointers and returns true if they point to the same address. So the compiler invokes that, and your code breaks.

IF you want to do string comparisons, you have to tell the compiler that you want to deal with strings, not pointers.

The C way of doing this is to use the strcmp function:

strcmp(var1, "dev");

This will return zero if the two strings are equal. (It will return a value greater than zero if the left-hand side is lexicographically greater than the right hand side, and a value less than zero otherwise.)

So to compare for equality you need to do one of these:

if (!strcmp(var1, "dev")){...}
if (strcmp(var1, "dev") == 0) {...}

However, C++ has a very useful string class. If we use that your code becomes a fair bit simpler. Of course we could create strings from both arguments, but we only need to do it with one of them:

std::string var1 = getenv("myEnvVar");

if(var1 == "dev")
{
   // do stuff
}

Now the compiler encounters a comparison between string and char pointer. It can handle that, because a char pointer can be implicitly converted to a string, yielding a string/string comparison. And those behave exactly as you'd expect.

jalf
This explanation rocks, _and_ advises std::string as well! I read over that the first time :)
xtofl