Does Your Code Not Compile?
The problem is that you're using some age old function notation that is only acceptable in C compilation and you compile your code as C++ (check the top right corner).
I'd suggest getting rid of this peculiar style and use the C++ compatible parameter definition.
So, instead of
void code_saver3(pntaa)
char *(*pntaa);
{
show_inventory(*pntaa);
}
use
void code_saver3(char ** pntaa)
{
show_inventory(*pntaa);
}
Apply the same logic for all of your functions.
Note
After this, your code compiles, but it has further problems.
Errors to Fix
Inventory
for (i = 0; i < ARRAY_SIZE; i++)
inventory[i] =(char *)malloc(50);
for(i = 0; i < ARRAY_SIZE; i++)
inventory[i] = "";
inventory[0] = "Sword";
inventory[1] = "Leather Armour";
inventory[2] = "Magic Potion";
inventory[3] = "Shield";
inventory[4] = "Back-pack";
So, in the first loop, you allocate memory for ARRAY_SIZE (20) C-strings in inventory.
In the second loop, you set inventory elements to point to the string literal "" (empty string). By this, you've lost pointers to the previous allocation (malloc). This is a memory leak.
Even worse, if anyone tries to write any inventory element (, which are right now string-literals, that mustn't be changed -- read: they are read-only) then it leads to a Segmentation Fault. (Memory corruption.)
Later, you set various inventory elements (0..4) to various string literals. (Again, we've already got memory leaks and this could be a source of problems if anyone tries to change the values stored in inventory.)
At this point, I'd advise that you make a decision:
- inventory is an array of buffers that you can write (sprintfs(buffer, ____)) OR
- inventory is an array of pointers to constant strings (const char ** inventory) where you set every pointer to point to an existing string that you mustn't change later.
I'd go with the second one as I think it's fine to set the inventory elements to point to various names. If you need to change a name, you can just point it to a new string. But it's up to you. Just know what you're doing.
potion_choice()
char potion_select = potion_choice(&potion, potion_select);
// ...
char potion_choice(char ** pnta, char pot_sel)
{
*pnta = "Potion of Skill";
*pnta++;
*pnta = "Potion of Stamina";
*pnta++;
*pnta = "Potion of Luck";
printf("Please choose a magic potion: \n");
printf("1: S(K)ill\n");
printf("2: (S)tamina\n");
printf("3: (L)uck\n");
do
{
pot_sel = getchar();
pot_sel = toupper(pot_sel);
} while (pot_sel != 'K' && pot_sel != 'S' && pot_sel != 'L');
return pot_sel;
}
As you can see, in the first line you set postion_select to the return value of potion_choice, while also being an input (but not output!) parameter of the same method.
I'd start the clean-up job by removing the second parameter (potion_select) from the potion_choice method. Instead, I'd declare potion_select as a local variable.
Furthermore, what this method is supposed to do (based on the name) is to ask a user input for selecting a potion. This method shouldn't manipulate the potions array (pnta). I would set up these values where the rest of the initialization happens.
Also, you have an array that stores the various potions, yet you display static values, not what the actual potions array contains.
One serious problem is with the calling of the method. You did
char potion_select = potion_choice(&potion, potion_select);
where you get the address of potion, which is a char ***, instead of char **. Then you write this array, which leads to another memory corruption. Remove the "address of" (&) operator.
show_inventory()
Similarly to the above, show_inventory() is called with the wrong argument type (char ***, instead of char **).
show_inventory(&inventory);
You should remove the "address of" (&) operator in this case as well.
The method itself also has problems.
void show_inventory(const char ** pnta)
{
while (*pnta != "")
{
printf("%s\n", *pnta);
*pnta++;
}
}
The problem here is that you keep going as long as *pnta (i.e. inventory[i]) is not empty. But what if your whole inventory is full? Then you'll keep reading memory after the inventory, which you have no business touching. This way, you'll read memory garbage.
I'd add an extra check if you haven't read and printed more than ARRAY_SIZE elements.
code_saver3()
When you call this method, you have the same problem with the above two cases: wrong pointer type. The same fix can be used.
The Amended Code
I'll post it in another answer as I've reached the maximum character length. :)