omg != omg ? (Comparing character arrays)

Started by
5 comments, last by 3Effex 17 years, 12 months ago
Hello All, I am currently making a 'messageHandler' class for a game of mine (It's just a test, really). At the moment I can use it like so: MessageHandler.addMessage("deleteAllEmitters"); MessageHandler.handleMessages(); MessageHandler.flushMessages(); However, I can't make it so I can type into the console something like 'deleteAllEmitter' and make it do the same thing...Here's some code:

	if(key == 'y')
		{	
			//Getting Input so we know the size of our pointer thingy
			char input[50];
			cin >> input;
			
			int inputLength = strlen( input );//Getting the Size

			char *pInput;	//Creating a char array of the right size
			pInput = new char[inputLength]; 
			pInput = input;	//Setting one to the other
			
			//Testing
			GameControl.addMessage( pInput );
			if(pInput == "omg")
				cout << "Message 'omg' was received properly...Thats a start...\n";
			else
				cout << pInput << " != omg...?\n";
		}

If i type in 'omg' the output is: 'omg != omg ...?' Which is just strange :) P.S, just incase here is the addMessage() function:

void Message_Handler::addMessage(char* message)
{
	MessageList.push_back( message ); 
	cout << "Message Added: " << message << endl;
}

What am I doing wrong?
Advertisement
C does not support string comparision in the form of character arrays. You would need to use the function strcmp(pInput, "omg") which returns 0 if they are equal, or declare pInput to be a string class, be sure to include <string> if you do this. I would suggest the latter, but the former is a fine solution also.
You should be using std::string in C++ and not char* when you want to use strings.
I think you can use function call strcmp(const char* str1, const char* str2) In order to use this function you need to include header call <string.h>. This function will return 0 when the str1 and the str2 are the same. If the str1 is less than str2 then it will return negative number. If the str1 greater than str2 It will return positive number.

Hope that help!
DinGY
Yesterday is history.Tomorrow is a mystery. Today is a gift"

pInput = input;//Setting one to the other
You are assigning the adress 'input' char array to the 'pInput' pointer variable, but not copying any char's! Maybe you want to do something like
for ( int i=0; (i < strlen(input)) && (i < 50): ++i )  pInput=input;

or
std::strncpy( input, pInput, 50 );

or simply use std::string, as others suggested.

pInput == "omg"

Here, you are checking if pInput points to the same adress as some "omg" string. That is highly unlikely. strcmp/strncmp or std::string::operator== to teh rescue!

<nitpick>invisal: The <string.h> header is a C header, the Standard C++ versions of the C headers have no .h suffix. The C++ified C functions are found in namespace std.</nitpick>
To expand a little on the other posts, a pointer is simply a variable which stores a memory address. This stored memory address is typically the location of a variable, but this is not always the case (you can set a pointer to 0 for example, and there is not valid object at the memory address 0).

When you compare two pointers, you compare the addresses which are stored in the two pointer variables and NOT the objects at those addresses.

int main(){ char* pchar = new char; if(array == "Hello") {    //... }}


In the above code we have tried to compare a character pointer with "Hello". "Hello" is called a string literal. A string literal is a variable of type const char[], that is a const character array. In this example we have a string literal "Hello" which has a type of const char[6].

Arrays have the property that they can be implicitly converted into a pointer to the first element of the array. This means that you can use the name of the array as if it were a pointer which stores the memory location of the first element in the array. As an example, "Hello" can be implicitly converted to a const char pointer which contains the memory address of the character H.

With that in mind, it should be a bit clearer as to what is going on in the above example.

if(pChar == "Hello")


The above line is treated as a comparison between two pointers. The reason for this is that there is no operator== defined in C++ which compares a const char[6] to a char*. The only operator== that can be called is the operator== which has a prototype of

bool operator==(T* ParameterOne, T* ParameterTwo)

Where both parameters are of the same type. Since pChar is a char* and our string literal "Hello" is a const char[6] which has an implicit conversion to both const char* and char*, the operator== with the following prototype is called. #1

bool operator==(char* ParameterOne, char* ParamterTwo)

The above prototype, as mentioned before, simply compares the memory addresses stored in the two pointer variables. In the case of pChar, this will be the address returned from the call to new char. In the case of our string literal "Hello", the const char[6] will be implicitly converted to a pointer to the first character of the array, namely a pointer which stores the memory address of the letter H. Clearly the address of letter H and the address returned from our call to new char are different, and so the comparison returns false.

Your case is slightly different in that the pChar is pointing to a dynamic array rather than just a dynamic char.

#include<cstring>int main(){ char* pChar = new char[6]; std::strcpy(pChar, "Hello"); if(pChar == "Hello") {  //.. }}


This is exactly the same as the previous example, as you are still comparing a variable of type char* with a const char[6], which can only result in the comparison operator for two pointers being called. Clearly pChar will point to the memory address returned from new char[6], which in this case also now happens to be the location of a character array containing the word Hello. Our string literal is still a const char[6] which has an implicit conversion to char* and so the operator== stated in the earlier example is called. It is important to realize that the const char[6] of the string literal and the char[6] returned from our call to new char[6] are completely different objects with completely different memory addresses, and so pointers to them can never be equal.

Clearly this pointer comparison is not what you intended, you merely wanted to compare the two arrays that the pointers point to, and not the addresses of there first elements. To do this for character arrays, there is a function called strcmp.

The correct code would then be

#include<cstring>int main(){ char* pChar = new char[6]; std::strcpy(pChar, "Hello"); if(std::strcmp(pChar, "Hello") == 0) {  //Two strings are equal }}


The functions strcpy and strcmp are inherited from C.

Now C++ provides a much neater way of going about this. The C++ standard Library contains a string object which encapsulates much of what you are trying to do. It also makes use of operator overloading to provide a more natural interface for dealing with strings. The above code, for example, can be replaced with the equivalent C++ code of

#include<string>int main(){  std::string One = "Hello";  if(One == "Hello")  {    //Two strings are equal  }}


In the above code, the constructor for the std::string encapsulates the previous examples calls to new char[6] and to std::strcpy. The operator== for an std::string and a const char* is overloaded to encapsulate the call to std::strcmp.

The main advantages of using std::string instead of explicitly using strcpy and strcmp yourself are:

  • It handles all memory management for you - you do not have to worry about using new and delete to allocate the string, this is all handled for you.

  • It allows you to do the same thing in much fewer lines of code

  • It makes your code more readable

  • It makes you more productive


    For a full list of the functions supported by std::string, you should consider buying a reference book like The C++ Standard Library by Josuttis.



    #1 - (NOTE the conversion from const TYPE[] to TYPE* applies only to string literals, const int[6] cannot be implicitly converted to type int*, though you could convert it explicitly).
  • Thanks for the help everyone, that sorted it out quick smart ;)

    This topic is closed to new replies.

    Advertisement