Okay, so I've run into another weird problem that I'm not sure how to solve. So as part of the text adventure I've been writing to help me learn C++, I built a function that displays the player's inventory and lets them select things from it and embedded it in a larger function that shows their stats, location, and character portrait. Those functions are as follows:

I found out that in a certain part of my text adventure it was possible for a player to progress and be pronounced healed even when they hadn't drunk a healing potion from their inventory and just opened their inventory and exited instead. To fix this, I built a loop:

You may notice the cout statements at the end of the inventory function and the loop. I put them there to test a theory I had and sure enough, they print out a sequence of 800210. Basically if the player drinks the potion I want the sequence to be 800, and the function modifies the variables to those values at least within itself.

However, outside of the function the variables remain unmodified, causing my loop to keep repeating itself and a whole host of problems down the road in my program as the player sits on a healing potion and is horribly wounded as opposed to patching themselves up.

If I could make it so that the variable defining statements in the function affected the variables more globally (most importantly, in main()) then things would be awesome, but I'm just not sure how to do that.

So, once again, I seek advice from more experienced programmers, is there anything I can do to make this work? I would be sorely grateful for any help I could get.

07-19-2012

jsrig88

Hi, I haven't read your code yet, but I have read the rest of the question. Basically you just want to research pointers. Then references, but mostly pointers. In newer languages, such as Java, pointers/references tend to be used fairly implicitly, but C++ is pretty much completely direct in distinguishing between whether you're using that stuff or not.

Basically when you pass a variable as an argument to a function in C++, the value of that variable gets copied over to the function. That means that you're working with two different copies that start off with the same value. Variables, by default, just have "ordinary" values in them, like numbers or alphanumerical sequences or something. However if you declare a variable to be a pointer, then the value of that variable is really just an address to a different location on the computer. So if you pass a pointer to a function, instead of an "ordinary" variable, the function receives the memory address, NOT the actual data. But doing that lets both the function and whatever is calling the function mess with the same piece of data (the contents of the same memory address), and this is basically how you do what you're describing.

Again newer languages tend to handle this somewhat internally, such as in Java. C++ and VB.Net are fairly explicit about it though, with good reason for the contexts in which they're used. It might take you a little while to learn to work with pointers, but that's something you'll need to research.

And if I misunderstood your question and actually just repeated a bunch of stuff you already know, sorry.

07-19-2012

chaucer345

Quote:

Originally Posted by jsrig88

Hi, I haven't read your code yet, but I have read the rest of the question. Basically you just want to research pointers. Then references, but mostly pointers. In newer languages, such as Java, pointers/references tend to be used fairly implicitly, but C++ is pretty much completely direct in distinguishing between whether you're using that stuff or not.

Basically when you pass a variable as an argument to a function in C++, the value of that variable gets copied over to the function. That means that you're working with two different copies that start off with the same value. Variables, by default, just have "ordinary" values in them, like numbers or alphanumerical sequences or something. However if you declare a variable to be a pointer, then the value of that variable is really just an address to a different location on the computer. So if you pass a pointer to a function, instead of an "ordinary" variable, the function receives the memory address, NOT the actual data. But doing that lets both the function and whatever is calling the function mess with the same piece of data (the contents of the same memory address), and this is basically how you do what you're describing.

Again newer languages tend to handle this somewhat internally, such as in Java. C++ and VB.Net are fairly explicit about it though, with good reason for the contexts in which they're used. It might take you a little while to learn to work with pointers, but that's something you'll need to research.

And if I misunderstood your question and actually just repeated a bunch of stuff you already know, sorry.

No, actually I'd read the tutorial for pointers on this site and had had problems figuring out what they were for until just now. I get it now, if I want to section my code into functions to keep things organized, then I'll have to designate pointers so that I'm working with the same piece of data! Thank you so much! I will give it a try and see if it works.

07-19-2012

Elysia

Look into references rather than pointers for this.

07-20-2012

chaucer345

Quote:

Originally Posted by Elysia

Look into references rather than pointers for this.

Hmm... I guess you're right, I tried using pointers to provide the location of the variables of interest in my if statements/case switches, defining the pointers like this:

So I guess I just don't understand pointers and am horribly misusing them.

I thought that writing in *lockpickptr would cause the program to search out what was stored at the memory address of lockpick and evaluate for the variable I defined as int lockpick and thus everything in the code would work out. I guess not. Is there something I'm missing here?

07-20-2012

laserlight

Quote:

Originally Posted by chaucer345

But now the code won't even compile and every line that has a pointer comes back with a compiler error saying:

That is because you did not change the type of your parameters, i.e., those parameters are not pointers.

Reference parameters would indeed be a better approach here: you get the call by reference mechanism that you need, and you don't need to change the calling syntax or your function implementation.

07-20-2012

chaucer345

Quote:

Originally Posted by laserlight

That is because you did not change the type of your parameters, i.e., those parameters are not pointers.

Reference parameters would indeed be a better approach here: you get the call by reference mechanism that you need, and you don't need to change the calling syntax or your function implementation.

What do you mean by the type of parameters? You mean like ints or floats? I'm very sorry, but I'm just not sure what you're talking about with this one. Would it be possible for you to give me a short example?

I also tried redoing this using references instead of pointers but I had the same problem and the cout statements started giving me very strange values.

Clearly I'm missing something very important here, as the loop still keeps going and my cout statements are giving me a sequence of 804277200214277200
which makes no sense at all. I'm really getting very confused here. Is there some key concept I'm missing? I thought from my research that references just served as aliases for variables defined in other functions and if I just defined some references for the variables I wanted to modify I would be able to use them and modify them as if they were those variables in a function aside from the function in which they were defined. Is that wrong?

07-20-2012

Elysia

What you did is correct. More context is needed to figure out what's wrong.
Regarding pointers, here is how to use them correctly:

What do you mean by the type of parameters? You mean like ints or floats? I'm very sorry, but I'm just not sure what you're talking about with this one. Would it be possible for you to give me a short example?

The type of healingpotionptr is int, not pointer to int, hence the expression *healingpotionptr is invalid.

Quote:

Originally Posted by chaucer345

Here's how I defined my references:

That was completely unnecessary. All you needed to do was to call the function by passing the arguments.

Quote:

Originally Posted by chaucer345

I'm really getting very confused here. Is there some key concept I'm missing?

Yes. You're missing the key concept of starting small, then building up on what works. Look at your inventory function: holy 14 parameters, Batman! Spiderman recommends that you don't have functions that require more than 8 legs to count the parameters; 5 or 6 is usually a more palatable maximum for non-superhero programmers.

If I were you, I would start with an inventory of just say, healing potions. Get your inventory system to work such that the player can use healing potions, thus reducing the inventory count, and find/buy healing potions, thus increasing the inventory count.

Once you have this working, think of how you can write a class (or at least an aggregate struct) to model an inventory so that you can pass around an inventory object (by reference) rather than having to pass around an argument for each item type in the inventory.

07-20-2012

chaucer345

Okay, so in an attempt to give the requested context I threw together a full program that was just the essential functions and portions of main() with easy to visualize cout statements that would display what was going on. The program compiles fine, if nothing else, and illustrates the problem (Also I know there's probably a bunch of junk variables floating around in there that aren't used for anything, I apologize for the lack of clarity):

Interested parties can throw it in a compiler and see for themselves, but the problem is clear. The references are modified fine in the function, but for some reason all the variables in the main function stay the same. That implies that the references I wrote in still aren't doing what I want them too, though the modification statements within the function are. Now that the full source code for the problem area is available, does anyone have ideas as to why?

Quote:

Originally Posted by laserlight

Yes. You're missing the key concept of starting small, then building up on what works. Look at your inventory function: holy 14 parameters, Batman! Spiderman recommends that you don't have functions that require more than 8 legs to count the parameters; 5 or 6 is usually a more palatable maximum for non-superhero programmers.

If I were you, I would start with an inventory of just say, healing potions. Get your inventory system to work such that the player can use healing potions, thus reducing the inventory count, and find/buy healing potions, thus increasing the inventory count.

Once you have this working, think of how you can write a class (or at least an aggregate struct) to model an inventory so that you can pass around an inventory object (by reference) rather than having to pass around an argument for each item type in the inventory.

Okay... this is where I shamefully admit my ignorance. The honest answer for why I didn't do all that stuff is that I don't know what any of it is. Very sorry, I'll get to researching.

07-20-2012

Elysia

breathedeep doesn't take its arguments by reference.
But you need to clean this up. Start putting stuff into structs, at the very least, as recommended.
And work on your indentation.

07-20-2012

chaucer345

It worked! Thank you so much.

You know, as I'm using it as a learning exercise anyway, I think I'm actually going to rewrite this program from scratch (minus the string literals). I've learned so much in the process of writing it that I keep running into problems where my old code just isn't built the same way the new code is and it's left me with a bunch of dead leftover junk that really needs cleaning. Thank you all for your help, and your patience. Hopefully next time I post about this project, things will be a little easier to read and I'll have a more complex grade of problem.

07-20-2012

rogster001

That big stack of variable declarations can be organised as laserlight says you can use structs - a certain type of player might have several attributes - you can group these attributes into your own datatype - a struct goblin, having goblin hits, goblin resistance etc. Further to that is the idea of Classes - Class player has hitpoints, resistance, status etc as well as working functions to do stuff- things common to all your character types - and then you subclass into your other types like wraith - which has a scare factor also, but still has all the things player has - as they are of type player too. Barring all that stuff, you dont need to declare all of your variables all at once, maybe look and see if any can be declared just when they are needed. Also north, east, south, west - things like that are constant - they can be declared as so and use CAPS to outline them in the code.