Sign in to follow this  

Nested If Statements

This topic is 4858 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

For some reason Dev-C++ won't let me call functions within nested if statements. When I try and compile, it compiles correctly, but a warning comes up that I am just referring to the function, not calling it. Here's what I'm trying to do: if(!strcmp(usrinp,exam)) { cout << endl; cout << "What would you like to examine?\n"; scanf("%s",item); if(!strcmp(item,item_name)) { cout << endl; cout << item_desc << endl; usr_menu(); } else { cout << endl; cout << "You don't see that anywhere."; usr_menu(); } } else { cout << "That is not a valid command.\n"; usr_menu(); } What I am basically trying to do is to allow the person playing my text adventure to type the word "examine", the program asks them what they would like to examine, they type in the object, and the program checks whether or not the object is in their location (or room). If it is, it displays the object's description, and if its not, it displays the error message. It then returns back to the usr_menu() or: > where they can input another command. Why isn't this code working? Is there an easier way of doing this? Thanks for your help.

Share this post


Link to post
Share on other sites
Post the errors that you are getting.


if(!strcmp(usrinp,exam))
{
cout << endl;
cout << "What would you like to examine?\n";
scanf("%s",item);
if(!strcmp(item,item_name))
{
cout << endl;
cout << item_desc << endl;
usr_menu();
}
else
{
cout << endl;
cout << "You don't see that anywhere.";
usr_menu();
}
}
else
{
cout << "That is not a valid command.\n";
usr_menu();
}




Also use formatting and "source" tags.

Share this post


Link to post
Share on other sites
Yeah, I'd like to see the errors too. Maybe it's just saying that usr_menu() is gonna get called no matter what, so you might as well put it after all of the if statements. Just a wild guess, though. I'm not familiar with GCC's errors and warnings.

Share this post


Link to post
Share on other sites
I didn't get any errors, only a warning saying that usr_menu() was a referrer and did not call a function. Then when I ran it it won't call the function, it just ends the program.

And sorry about not using the source tag, I wasn't sure what it was until I just looked it up in the FAQ.

Share this post


Link to post
Share on other sites
Show us the whole thing. The problem may not be in the code you've posted. For example if the nested-if you posted is itself inside of an if statement or if it is called from within an if statement then it is possible than none of this nested-if is ever given a chance to run.

More code please. Plus give us the EXACT wording of the warning you are getting(cut and paste it).

Share this post


Link to post
Share on other sites
Here's the exact code, not the simplified version I posted before:


#include <iostream>
#include <stdlib.h>
#include <string.h>

using namespace std;

// Menu Screens
void mainmenu(void);
void newgame(void);
void loadgame(void);
void helpfiles(void);
void credits(void);

// In-Game Locations
void crashsite(void);
void crashsite_menu(void);
void clearing(void);
void clearing_menu(void);

// Possible Location Exits
char north[] = "north";
char south[] = "south";
char west[] = "west";
char east[] = "east";
char up[] = "up";
char down[] = "down";
char in[] = "in";
char out[] = "out";

// Object Variables
char dir[128];
char item[128];
char item_name[128];

// In-Game Keywords
char look[] = "look";
char examine[] = "examine";
char take[] = "take";
char drop[] = "drop";
char eat[] = "eat";

void wrapPrint(char* str, int maxwidth)
{
// seps holds the character which denotes the separation of two words (a space)
char seps[] = " ";
char* token;

int currentpos = 0;

// loop while there are still words to print
token = strtok(str, seps);
while(token)
{
// if a word is too big
if(currentpos + strlen(token) > maxwidth)
{
cout << endl;
currentpos = strlen(token);
}
else
{
cout << " ";
currentpos += strlen(token) + 1;
}
cout << token;
token = strtok(NULL, seps);
}
cout << flush;
}

void mainmenu(void)
{
int action;
cout << endl;
cout << "*****************************************" << endl;
cout << "* *" << endl;
cout << "* A W A K E N E D *" << endl;
cout << "* *" << endl;
cout << "*****************************************" << endl;
cout << endl;
cout << "1. New Game" << endl;
cout << "2. Load Game" << endl;
cout << "3. Help File" << endl;
cout << "4. Credits" << endl;
cout << endl;
cout << "> ";
cin >> action;
cout << endl;
cout << endl;
switch(action)
{
case 1:
newgame();
break;
case 2:
loadgame();
break;
case 3:
helpfiles();
break;
case 4:
credits();
break;
default:
cout << "Please enter the designated number of the menu you wish to access.";
cout << endl;
cout << endl;
mainmenu();
break;
}
}

void newgame(void)
{
char intro1[] = "It is an age when mankind has overcome its confinement of one planet, and has colonized hundreds of worlds across the galaxy. However, much still remains to be explored, and intelligent life in the universe has still yet to be discovered.\n";
wrapPrint(intro1,78);
cout << endl;
char intro2[] = "You are among a small team of researchers dispatched to chart new planets, safe lightspeed routes, and any life you may encounter on your journey. You are only one of thousands of other teams, just a drop in the bucket, and conveniently go unnoticed when you are forced to crashland on an uncharted planet after a mysterious engine failure.\n";
wrapPrint(intro2,78);
cout << endl;
char intro3[] = "You, a lone mercenary, are the team's sole hope of survival. Equipped with a machine gun, a shotgun, and a spare pistol, along with some extra ammo and enough rations for your team for 10 days, you must seek out shelter and extra food if you and your team are to survive.\n";
wrapPrint(intro3,78);
cout << endl;
char intro4[] = "Still, other dangers lie before you. Who knows what unthinkable horrors reside in the dense brush of this strange planet....\n";
wrapPrint(intro4,78);
cout << endl;
cout << endl;
system("PAUSE");
cout << endl;
cout << endl;
cout << endl;
crashsite();
}

void crashsite(void)
{
cout << "THE CRASHSITE" << endl;
cout << "-------------" << endl;
char desc[] = "You are awakened by the deafening sound of silence. After hearing shrill screams in your last moments of consciousness, the sudden soundlessness is unnerving. It's very quiet. But all the time you can hear some eerie, raspy breathing. The sound wasn't coming from you are any of the other survivors; it is more *around you* than anything. It seemed like the entire world surrounding you is alive with excitement and vigor. You don't have a good feeling about this place, and you have long since learned to trust your intuition.\n";
wrapPrint(desc,78);
cout << endl;
char desccont[] = "You slowly and carefully check for any survivors among the crisp carcasses of burnt researchers. Twelve others have survived. You collect all usable supplies from the site, and decide that you should get moving. You aren't safe just standing around here waiting for something to attack you. Besides, there's nothing left here for you anyway.\n";
wrapPrint(desccont,78);
cout << endl;
crashsite_menu();
}

void crashsite_menu(void)
{
cout << "> ";
scanf("%s",dir);
if(!strcmp(dir,north))
{
cout << endl;
cout << "You cannot go in that direction.\n";
cout << endl;
crashsite_menu();
}
else if(!strcmp(dir,south))
{
cout << endl;
cout << "You cannot go in that direction.\n";
cout << endl;
crashsite_menu();
}
else if(!strcmp(dir,west))
{
cout << endl;
cout << "You cannot go in that direction.\n";
cout << endl;
crashsite_menu();
}
else if(!strcmp(dir,east))
{
cout << endl;
cout << "You cannot go in that direction.\n";
cout << endl;
crashsite_menu();
}
else if(!strcmp(dir,look))
{
cout << endl;
cout << "You look around and see nothing of interest.\n";
cout << endl;
crashsite_menu();
}
else if(!strcmp(dir,examine))
{
cout << endl;
cout << "What would you like to examine?\n";
scanf("%s",item);
if(!strcmp(item,item_name))
{
cout << endl;
cout << "Item description.\n";
cout << endl;
crashsite_menu;
}
else
{
cout << endl;
cout << "You don't see that.\n";
cout << endl;
crashsite_menu;
}
}
else if(!strcmp(dir,take))
{
cout << endl;
cout << "What would you like to take?\n";
scanf("%s",item);
if(!strcmp(item,item_name))
{
cout << endl;
cout << "Taken.\n";
cout << endl;
crashsite_menu;
}
else
{
cout << endl;
cout << "You don't see that.\n";
cout << endl;
crashsite_menu;
}
}
else if(!strcmp(dir,drop))
{
cout << endl;
cout << "What would you like to drop?\n";
scanf("%s",item);
if(!strcmp(item,item_name))
{
cout << endl;
cout << "Dropped.\n";
cout << endl;
crashsite_menu;
}
else
{
cout << endl;
cout << "You aren't carrying that.\n";
cout << endl;
crashsite_menu;
}
}
else if(!strcmp(dir,eat))
{
cout << endl;
cout << "What would you like to examine?\n";
scanf("%s",item);
if(!strcmp(item,item_name))
{
cout << endl;
cout << "Hmmm. Oddly satisfying.\n";
cout << endl;
crashsite_menu;
}
else
{
cout << endl;
cout << "That isn't edible.\n";
cout << endl;
crashsite_menu;
}
}
else
{
cout << "That is not a valid command. See \"Help Files\" for more information.\n";
cout << endl;
crashsite_menu();
}
}

void clearing(void)
{
cout << "THE CLEARING" << endl;
cout << "------------" << endl;
char desc[] = "You find yourself standing in the middle of a clearing. This area was obviously cleared deliberately, as nothing *natural* could have stripped those long, venomous-looking plants bare like that and thrown them aside with such intent.\n";
wrapPrint(desc,78);
cout << endl;
clearing_menu();
}

void clearing_menu(void)
{
cout << "> ";
scanf("%s",dir);
if(!strcmp(dir,look))
{
cout << endl;
cout << "You see long, venomous-looking plants here.\n";
cout << endl;
clearing_menu();
}
else
{
cout << endl;
cout << "That is not a valid command. See \"Help Files\" for more information.\n";
cout << endl;
clearing_menu();
}
}


void loadgame(void)
{
cout << "Loading Saved Game...";
}

void helpfiles(void)
{
cout << "Accessing Help File...";
}

void credits(void)
{
cout << "Credits...";
}

int main(void)
{
mainmenu();
cout << endl;
system("PAUSE");
return 0;
}



Here's the warning message I'm getting:

[Warning] statement is a reference, not call, to function `crashsite_menu()'

Share this post


Link to post
Share on other sites
Quote:
Original post by Matt Apple
Eight different times in your code you say...
crashsite_menu;
when you should say...
crashsite_menu();

Right. Without the parentheses, it acts as a pointer to the function, or a reference as the compiler called it. So that line of code would actually do nothing at all.

Share this post


Link to post
Share on other sites
Heh, your programming style reminds me of myself when I first wanted to write a text-based adventure game many years ago.

Anyway, your usage of nesting functions worries me.
You're always passing on control to another (or the same) function after you finished execution of a function. This will in practice work exactly as you intended...however, after playing the game for a long while, you'll see that you get a "stack overflow" error. You see, whenever you call a function, the program needs to store the address in memory it should return to after it finished running the code in your function. The program places this address on the "stack", now this stack-space is (of course) limited and if you fill it up you'll get this "stack overflow" error. Now, the reason why you're filling up the stack, imagine this scenario:

main() calls mainmenu(). Store return address to main() on stack.
player selects "new game". Store return address to mainmenu() on stack
newgame() calls crashsite(). Store return address to newgame() on stack.
crashsite() calls crashsite_menu(). Store return address to crashsite() on stack.

All code paths in crashsite_menu() leads to another call to crashsite(), which means that you've entered an infinite loop where every iteration results in storing the return address of crashsite_menu() on the stack...which fill effectively fill up your stack after a while.

If you're planning on continuing on this game, I suggest you rethink your design now before you inevitably run out of stack and got a couple of thousand lines of code to change in order to make it work..

Share this post


Link to post
Share on other sites
Quote:
Original post by CGameProgrammer
Luctus is totally right, but not only is the address of the function pushed to the stack, but any local variables and parameters to the function are also pushed to the stack each time.
Don't forget the stack frame pointer! [wink]

Share this post


Link to post
Share on other sites
Quote:
Original post by Luctus
Heh, your programming style reminds me of myself when I first wanted to write a text-based adventure game many years ago.

Anyway, your usage of nesting functions worries me.
You're always passing on control to another (or the same) function after you finished execution of a function. This will in practice work exactly as you intended...however, after playing the game for a long while, you'll see that you get a "stack overflow" error. You see, whenever you call a function, the program needs to store the address in memory it should return to after it finished running the code in your function. The program places this address on the "stack", now this stack-space is (of course) limited and if you fill it up you'll get this "stack overflow" error. Now, the reason why you're filling up the stack, imagine this scenario:

main() calls mainmenu(). Store return address to main() on stack.
player selects "new game". Store return address to mainmenu() on stack
newgame() calls crashsite(). Store return address to newgame() on stack.
crashsite() calls crashsite_menu(). Store return address to crashsite() on stack.

All code paths in crashsite_menu() leads to another call to crashsite(), which means that you've entered an infinite loop where every iteration results in storing the return address of crashsite_menu() on the stack...which fill effectively fill up your stack after a while.

If you're planning on continuing on this game, I suggest you rethink your design now before you inevitably run out of stack and got a couple of thousand lines of code to change in order to make it work..


Thanks for the feedback. How do you suggest I optimize this code. I've written a little bit more, another 8 functions worth, but its still under 700 lines so I don't mind changing it :)

Share this post


Link to post
Share on other sites
Quote:
Original post by Legend097
Quote:
Original post by Luctus
Heh, your programming style reminds me of myself when I first wanted to write a text-based adventure game many years ago.

Anyway, your usage of nesting functions worries me.
You're always passing on control to another (or the same) function after you finished execution of a function. This will in practice work exactly as you intended...however, after playing the game for a long while, you'll see that you get a "stack overflow" error. You see, whenever you call a function, the program needs to store the address in memory it should return to after it finished running the code in your function. The program places this address on the "stack", now this stack-space is (of course) limited and if you fill it up you'll get this "stack overflow" error. Now, the reason why you're filling up the stack, imagine this scenario:

main() calls mainmenu(). Store return address to main() on stack.
player selects "new game". Store return address to mainmenu() on stack
newgame() calls crashsite(). Store return address to newgame() on stack.
crashsite() calls crashsite_menu(). Store return address to crashsite() on stack.

All code paths in crashsite_menu() leads to another call to crashsite(), which means that you've entered an infinite loop where every iteration results in storing the return address of crashsite_menu() on the stack...which fill effectively fill up your stack after a while.

If you're planning on continuing on this game, I suggest you rethink your design now before you inevitably run out of stack and got a couple of thousand lines of code to change in order to make it work..


Thanks for the feedback. How do you suggest I optimize this code. I've written a little bit more, another 8 functions worth, but its still under 700 lines so I don't mind changing it :)


Well for starters Id suggest a main game loop to solve the problem Luctus pointed out.
At the moment your game keeps on going by jumping through the functions.
You should have one infinite loop in void main.
Basically that way functions will begin and end on a per frame basis.
Something like this(overly simplified)

while(1)
{
draw_area(current_area);
check_input(current_area);
}


-CProgrammer

Share this post


Link to post
Share on other sites
I feel generous tonight and I want to make sure you don't grow up to keep on writing code like that, so you get a specific Google link *and* starter code. :) But if you aren't familiar with the whole 'class' idea or with std::string, I'm going to leave you on your own for a bit; it'll do you some good to do more research by yourself. ;)

[google] "finite state machine" tutorial implementation C++

Each room becomes a 'state'.


// None of this is tested, but I hopefully didn't mess up
// anything *too* badly ^^;
class Room {
public:
Room(std::string desc) : description(desc) {}
// constructor. You will probably end up with a more
// elaborate one :)
void showDescription(); // output the description
// (see below), with whatever linewrapping etc. you want
// to do.
Room * handleInput(const std::string& userCommand);
// returns pointer to the new room
// This needs to behave the same basic way for every room,
// unless you want to make subclasses for each x.x But: you
// can add extra stuff to the room, like:
private:
std::vector<Item> itemsInThisRoom;
// to help out a bit. (You are on your own
// to define what an 'Item' looks like.)
Room * north; // room to go to if the user types "north"
// so on for other directions.
// The tricky part will be linking up all the rooms ;)
std::string description; // output when the user enters
// the room. I.e. it gets used in the showDescription()
// method :)
}

// Once you have a bunch of room creation working in code, you
// should start thinking about loading rooms from a file. :)

int main(int argc, char **argv) {
// First, create all rooms, and/or do the 'main menu' thing

Room * currentRoom = ...;
// whatever room the player starts in.
// There are good reasons for using pointers here, trust me ;)
std::string command;
while(1) {
currentRoom->showDescription();
cin >> command;
currentRoom = currentRoom->handleInput(command);
// handleInput should "return this;" if the command is invalid.
}
}

// One possible trick: use 0 (a null pointer) as a return value
// indicating that the player died, or that the game is over for
// whatever reason. Then you make your while loop just
// "while(room)", and put the end-of-game stuff after the loop.


Share this post


Link to post
Share on other sites

This topic is 4858 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this