C++ Compare char array with string

169,403

Solution 1

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.

Solution 2

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.

Solution 3

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")) {
  ..
}

Solution 4

"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.

Solution 5

There is more stable function, also gets rid of string folding.

// Add to C++ source
bool string_equal (const char* arg0, const char* arg1)
{
    /*
     * This function wraps string comparison with string pointers
     * (and also works around 'string folding', as I said).
     * Converts pointers to std::string
     * for make use of string equality operator (==).
     * Parameters use 'const' for prevent possible object corruption.
     */
    std::string var0 = (std::string) arg0;
    std::string var1 = (std::string) arg1;
    if (var0 == var1)
    {
        return true;
    }
    else
    {
        return false;
    }
}

And add declaration to header

// Parameters use 'const' for prevent possible object corruption.
bool string_equal (const char* arg0, const char* arg1);

For usage, just place an 'string_equal' call as condition of if (or ternary) statement/block.

if (string_equal (var1, "dev"))
{
    // It is equal, do what needed here.
}
else
{
    // It is not equal, do what needed here (optional).
}

Source: sinatramultimedia/fl32 codec (it's written by myself)

Share:
169,403

Related videos on Youtube

Chris Klepeis
Author by

Chris Klepeis

Current Interests: DDD Xamarin Blazor

Updated on October 07, 2020

Comments

  • Chris Klepeis
    Chris Klepeis over 3 years

    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.

    • NomeN
      NomeN almost 15 years
      try using a debugger to see whether var1 actually is filled with "dev1". Also, if var1 actually is a C++ style string use the c_str() function to get a c style string that can be compared to your char* using strcmp();
    • tchen
      tchen
      Looks like you are using raw C strings and not the C++ String class.
  • Martin York
    Martin York almost 15 years
    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.
  • Drew Delano
    Drew Delano almost 15 years
    I call this "Yoda Coding" (backwards is the expression, hmmm?). I'd prefer to use compile options to catch accidental assignments.
  • JaredPar
    JaredPar almost 15 years
    @Fred agree with you i do not. :)
  • paulm
    paulm almost 10 years
    Max compiler warning level, warnings as errors, yoda not required :)