C++ Compare char array with string

C++StringString Comparison

C++ Problem Overview


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.

C++ Solutions


Solution 1 - C++

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 - C++

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 - C++

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 - C++

"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 - C++

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)

Solution 6 - C++

your thinking about this program below

#include <stdio.h>
#include <string.h>

int main ()
{
char str[][5] = { "R2D2" , "C3PO" , "R2A6" };
int n;
puts ("Looking for R2 astromech droids...");
for (n=0 ; n<3 ; n++)
if (strncmp (str[n],"R2xx",2) == 0)
{
  printf ("found %s\n",str[n]);
}
return 0;
}
//outputs:
//
//Looking for R2 astromech droids...
//found R2D2
//found R2A6

when you should be thinking about inputting something into an array & then use strcmp functions like the program above ... check out a modified program below

#include <iostream>
#include<cctype>
#include <string.h>
#include <string>
using namespace std;

int main()
{
int Students=2;
int Projects=3, Avg2=0, Sum2=0, SumT2=0, AvgT2=0, i=0, j=0;
int Grades[Students][Projects];

for(int j=0; j<=Projects-1; j++){
  for(int i=0; i<=Students; i++) {
 cout <<"Please give grade of student "<< j <<"in project "<< i  <<  ":";
  cin >> Grades[j][i];
     
  }
  Sum2 = Sum2 + Grades[i][j];
	 Avg2 = Sum2/Students;
}
SumT2 = SumT2 + Avg2;
AvgT2 = SumT2/Projects;
cout << "avg is  : " << AvgT2 << " and sum : " << SumT2 << ":";
return 0;
}

change to string except it only reads 1 input and throws the rest out maybe need two for loops and two pointers

#include <cstring>
#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;
int main()
{
char name[100];
//string userInput[26];
int i=0, n=0, m=0;
cout<<"your name? ";
cin>>name;
cout<<"Hello "<<name<< endl;

char *ptr=name;
for (i = 0; i < 20; i++)
{
cout<<i<<" "<<ptr[i]<<" "<<(int)ptr[i]<<endl;
}   
int length = 0;
while(name[length] != '\0')
{
length++;
}
                    for(n=0; n<4; n++)
                {
                            if (strncmp(ptr, "snit", 4) == 0)
                            {
            cout << "you found the snitch "    <<        ptr[i];
                            }
                }
cout<<name <<"is"<<length<<"chars long";
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionChris KlepeisView Question on Stackoverflow
Solution 1 - C++John MillikinView Answer on Stackoverflow
Solution 2 - C++jalfView Answer on Stackoverflow
Solution 3 - C++JaredParView Answer on Stackoverflow
Solution 4 - C++sepp2kView Answer on Stackoverflow
Solution 5 - C++AraneaSerket6848View Answer on Stackoverflow
Solution 6 - C++101dolmationsView Answer on Stackoverflow