Problem with & and things...

Started by
7 comments, last by Zahlman 19 years, 1 month ago
Hi, I'm having a problem which I can't figure out. I have a orc class which inherits from my sprite class. It contains several functions and attributes including the following:-

public:
               char getDirection(){return mDirection;}
private:
               char mDirection; //The current direction the sprite is facing

mDirection should either be N, S, E or W. In my main program when I detect a collision between sprites, I want to do a feew things, depending on what direction the badguy sprite is facing. So first I create a badguy based on orc doing. orc *badguy = new orc; Then I have the following ccode

char direction = badguy->getDirection();
printf("direction %s ", &direction);

if(strcmp(&direction, "S") == 0)
{                                                            theSprite->setY(theSprite->getY()+10);
printf("This happened");
}

Ok so when I detect a collsion I get the direction, then I print to the console what the direction was, and finally if the sprite was facing S then I move the good guy sprite down 10 pixels. The problem is when I run the game and a collsion occurs "direction S" is printed to the console several times. However my if(strcmp) statement doesn't seem to say that direction and S are the same. Any ideas why this is??
Advertisement
strcmp requires that you submit null terminated strings as arguments. so you'd actually need to pass a 2 character string, not the address of a char variable. I'd expect very bad things to happen in your code. However, instead of solving your problem directly i'd suggest a complete redesign. use an enum instead:

enum Direction { N, S, E, W };std::string directionToText( Direction dir ){  std::string result;  switch( dir )  {    case N: result = "N"; break;    case S: result = "S"; break;    case E: result = "E"; break;    case W: result = "W"; break;  }  return result;}class Orc : public Sprite{public:    Direction getDirection() { return m_direction; }private:    Direction m_direction;};


then

Direction direction = badguy->getDirection();printf("direction %s ", directionToText(direction).c_str());if( direction == S ){    theSprite->setY(theSprite->getY()+10);    printf("This happened");}


forgive any syntactical errors

-me
Quote:Original post by siliconsurfer
The problem is when I run the game and a collsion occurs "direction S" is printed to the console several times. However my if(strcmp) statement doesn't seem to say that direction and S are the same. Any ideas why this is??


I do not think it is possible to compare strings and characters like that, but I may be wrong. Try something like this just to see if that is the case:
char direction = badguy->getDirection();char tmp[2];memset(tmp,0,2);snprintf(tmp,1,"%c",direction);printf("direction %s ", &direction);if(strcmp(tmp, "S") == 0){   theSprite->setY(theSprite->getY()+10);   printf("This happened");}


- Drew
Quote:Original post by Palidine
strcmp requires that you submit null terminated strings as arguments. so you'd actually need to pass a 2 character string, not the address of a char variable. I'd expect very bad things to happen in your code. However, instead of solving your problem directly i'd suggest a complete redesign. use an enum instead:

*** Source Snippet Removed ***

then

*** Source Snippet Removed ***

forgive any syntactical errors

-me


Fair enough, however in my orc class I was able to do the following with code.
if(strcmp(&mDirection, "N") == 0){setImage("data/orc_up.bmp"); setW(22); setH(26);}

Isn't this the same operation, except &mDirection is a member variable, and not returned from a function??
what you are doing with strcmp is very very very VERY bad. if you are coming to C from Java it is VERY important for you to understand that in C, strings are HACKS. they are evil and can get you into lots of trouble. the way the methods like strcmp know where the end of a string is, are by looking for a '\0' character at the end of them. you are passing the address of a char variable to the strcmp function. if the next piece of memory after your character does not happen to be a NULL character then unperdictable things can happen: crash, freeze, change the values of other things in memory, etc.

So the fact that it works in your other class is by pure dumb luck. it could very well be how your compiler structures things or how your object happens to get instantiated, or just some fact about the differences between member variables and regular stack variables and how they are represented in memory.

the important takeaway is that what you are doing is bad (even in the case where it works). you should either convert over to std::string if you want to stay with your method, or you should learn about how "strings" work in C/C++, or you should implement the enum method I described, or come up with another solution of your own devising.

-me
oh...also, this just occurred to me. there is no need for you to use the strcmp function at all in your current implementation. since it's a char you can just do:

char direction = badguy->getDirection();printf("direction %c ", direction); //note that it's %c not %s here b/c it's a char//also note that it's no longer &direction, it's just directionif(direction == 'S') //note that it's a single quote, not a double quote{    theSprite->setY(theSprite->getY()+10);    printf("This happened");}


it's more useful in C to think of chars as ints than as letters.

-me
Ok cheers, does direction = S compare ASCII values? If not how does do the comparison between differnt letters?

Cheers
Quote:Original post by siliconsurfer
Ok cheers, does direction = S compare ASCII values? If not how does do the comparison between differnt letters?

Cheers


so in C/C++, char is int with some hackery around it. a char is just a number that's hacked later so that it has "letter" meaning. a char is just the ASCII number that represents the letter. so char c is not really c, it's 99.

because it's basically an int, if you want to do things differently depending on what letter it is you can do things like switch:

char direction;switch (direction){    case 'N':      // do some stuff      break;    case 'S':      // do some stuff      break;    case 'E':      // do some stuff      break;    case 'W':      // do some stuff      break;    default:      // do some stuff in that case that it's not what you expect      break;}
Quote:Original post by siliconsurfer
Ok cheers, does direction = S compare ASCII values? If not how does do the comparison between differnt letters?

Cheers


The single quotes are important, but yes.

A char variable stores a single value; it is not a "string" even in the C sense. C-style "strings" are dangerous hacks that assume that the character pointed to and the bits of data that follow it in memory are all character-typed data which eventually end with a \0.

By the way, this:
theSprite->setY(theSprite->getY()+10);

is AWFUL.

The sprite itself should be handling this:
void Sprite::moveSouth(int distance) {  y += distance;  // Any other checking logic that used to be in the setter goes here.}

Then you can expose an interface with methods that do something and have a meaningful name. If you simply do everything through accessors and mutators then you are lying to yourself about encapsulation.
theSprite->moveSouth(10);

Later, we might change this to be a single 'move' method which accepts the direction as a parameter (either as a char or as the suggested enumeration value). Then we can directly do:
theSprite->move(10, badguy->getDirection());

Except that of course, we learn from the previous discussion, and avoid the accessor. The enemy object really should be more closely associated with its state anyway:
void enemy::move() {  mySprite->move(10, myDirection);}// where mySprite is a member variable of the enemy class...badguy->move();


OO isn't about keeping data out of the wrong places; it is about putting code in the right places.

This topic is closed to new replies.

Advertisement