Understanding [un]desirable functioning of my program.

I have been working on a small home project just to increase my skill as a c++ programmer. This project is a small inventory simulator program. I finished the basic code and got it working acceptably well. However, it does something I didn't program it to do. In particular, when inputting either a "give" or "drop" command, I programmed it to go to a second prompt, asking "Drop [or give] which item?: " HOWEVER, if i type "give sword" (for example) into the first prompt, it automatically gives me a sword. Bypassing the second prompt. I'm not sure what the heck is happening here. And i have no idea how this feature is happening. I was just hoping someone could give my code a look and explain it to me if possible :)

I'm not sure where the coding lies that allows this, so i'm afraid I have to just post the entire thing, sorry. Any help is really appreciated as i'm lost

Raistlin121.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
int main()
{
    //instructions
    cout << "Welcome to the inventory simulator!\n"
         << "Type 'give' to place an item in your inventory.\n"
         << "'drop' will remove it.\n"
         << "'view' will display the contents of your inventory.\n"
         << "'exit' will close the program.\n"
         << "limit of 10 items in inventory.\n" << endl;
    
    bool bLoop = true;
    string input;
    string* pszArr = new string[11];
    for(int i = 0;i < 10; ++i) //initializes inventory default to be "---" - NOTE:OPTIMIZE LATER
    {
            pszArr[i] = "---";
    }
    
    while(bLoop == true)
    {
                input = getUserInput();
                bLoop = operateCommand(input, pszArr);               
    }
    
    delete[] pszArr; //deletes the memory on the heap allocated to inventory
    pszArr = 0;
      
    system("PAUSE");
    return 0;
}
     
//______________________________________________________________________________-     

string getUserInput()
{
       bool bVarOK;
       string szInput;
       
       while(bVarOK == false) //if input is invalid, tells user, and gets new input.
       {
                   cout << "Enter a command: " ;
                   cin >> szInput;
                   cout << endl;
                   
                   bVarOK = testInput(szInput);
                   if(bVarOK == false)
                   {
                            cout << "\nThat is not valid.\n\n";
                   }
       }
       return szInput; //returns a *valid* value
       
}

bool operateCommand(string szInput,string* invArray)
{
     if(szInput == "give")
     {
                giveItem(invArray);
                return true;
     }
     else if(szInput == "drop")
     {
                dropItem(invArray);
                return true;
     }
     else if(szInput == "view") 
     {
                viewInventory(invArray);
                return true;
     }
     else          //If input is "exit", go to main() and close program
     {          
                return false;
     }
     
}

void viewInventory(string* inventory) //outputs all elements in the inventory array
{
     for(int i = 0;i < 10;i++)
     {
           cout << inventory[i] << endl;
     }
     cout << endl;
     return;
}

void giveItem(string* inventory) //give item command
{
     bool bVarOK;
     string szInput;
     while(bVarOK == false)
       {
                   cin >> szInput;
                   
                   bVarOK = testItemInput(szInput);
                   if(bVarOK == false)
                   {
                            cout << "That is not valid.\n\n";
                   }
       }
    
       for(int i = 0;i < 10; i++)
       {
             if(inventory[i] == "---")
             {
                             inventory[i] = szInput;
                             return;
             }
                             
       }
       cout << "Your inventory is full\n";
}
 
void dropItem(string* inventory)
{
     bool bVarOK;
     string szInput;
     while(bVarOK == false)
       {
                   cout << "Drop which item?: " ;
                   cin >> szInput;
                   
                   bVarOK = testItemInput(szInput);
                   if(bVarOK == false)
                   {
                            cout << "That is not valid.\n\n";
                   }
       }
       for(int i = 0;i < 10; i++)
       {
             if(inventory[i] == szInput)
             {
                             inventory[i] = "---";
                             return;
             }
                             
       }
       cout << "\nYou can't drop that\n\n";
}


bool testInput(string szCommand) //tests input is a viable command
{
     if(szCommand == "give")
     {
                  return true;
     }
     else if(szCommand == "drop")
     {
                 return true;
     }
     else if(szCommand == "view")
     { 
                 return true;
     }
     else if(szCommand == "exit")
     {
                 return true;
     }
     else
     {
                 return false;
     } 
}

bool testItemInput(string szInput) //checking input is a real item
{
     if(szInput == "sword")
     {
                  return true;
     }
     else if(szInput == "bow")
     {
                 return true;
     }
     else if(szInput == "helmet")
     { 
                 return true;
     }
     else if(szInput == "chestpiece")
     {
                 return true;
     }
     else if(szInput == "leggings")
     {
                 return true;
     }
     else if(szInput == "gloves")
     {
                 return true;
     }
     else if(szInput == "bracers")
     {
                 return true;
     }
     else if(szInput == "boots")
     {
                 return true;
     }
     else
     {
                 return false;
     } 
}     
Simple, cin "Cuts" a input each time it finds a whitespace (A ' ', '\n', '\t' )
So you may want to use cin.getline instead. It works on char pointers only i think, so you may want to do something like this:
1
2
3
char Command[512];
cin.getline(Command,512,'\n');
szInput = Command;

instead of
 
cin >> szInput;
Last edited on
If you're using strings, just use getline(cin, str);
Ahhh right. To be honest I was hoping to make it all work in a single prompt in the end. So this was a bit of a happy accident. The only problem now, is as it is running correctly, but in a way I never intended, could there be some glitches in certain scenarios?
what do you mean by never intended?
I mean that I programmed it so that the commands use two prompts. 1)" Which command?" (give, drop, view), and 2) "Drop [or give, depending on the first choice] which item?".

While using "cin >> " it operates with only a single prompt. and this is actually a more efficient way of doing it from the users point of view, but I'm unsure if using "cin >> " in this way could have some bugs in certain scenarios? (Sorry if i'm making no sense :) This is very much a personal project, and i'm very much a beginning programmer)

Operation I intended:


Enter a command: give 
Give which item?: sword

Enter a command: view
sword
---
---
---
---
---
---
---
---
---

Enter a Command: exit


Also works:

Enter a command: give sword
Give which item?:   [note: the program skips this prompt in this case]
Enter a command: view

sword
---
---
---
---
---
---
---
---
---

Enter a command: exit

Well... There aren't many bugs i know of about cin.
The biggest bug i know about console input is, when you have the following code:
1
2
int Number = 0;
cin >> Number;

and input some text.
I don't know if a bug really happens with cin.
I know it does with scanf, the C-like version of cin.
But, in case a bug actually happens, you can get the input as text, have your own "strtoul" (String to Number) checked version (Check by yourself if what user entered actually IS a number or not).
Or, with cin, you may clear the error buffer.

What actually the error does (on scanf, again, i'm not sure if it will happen on cin too) is:
if(Input isn't a Number)
Set a Error Flag
if(Error Flag is Set)
Skip All Input Requests

This post may be useless. But in case cin still has this bug, this may help you a bit.
thanks :) I'm happy with any advice to be honest, actual people seem to explain programming better than google. ;P
Wait, what was the question again?

If you're wondering why this works:
Enter a command: give sword
Give which item?:
Enter a command: view

sword
---
---
---
---
---
---
---
---
---

Enter a command: exit


Here's what happens:
1. Program asks you to enter a command. Say you enter "give sword".
2. Program reads in "give", stopping at the space character (cin >> something always stops when it sees a whitespace character).
3. Program asks you to enter an item. There's already " sword" in the input buffer, so cin doesn't need to get anything from the user and just reads in "sword". (the space character at the beginning is ignored)

(That's a pretty simplified explanation, I'll admit, but it's close enough....)

If you want to read a whole line of text (including spaces and all), use
1
2
string input;
getline(cin, input);

(I think someone already mentioned that)

Oh, and @EssGeEich:
That's not really a "bug".
It's supposed to do that...what else would you expect it to do?
Anyways, you can always do (well, assuming cin.sync() does its job properly, which usually you don't have to worry about it):
1
2
3
4
5
6
7
int num;
while (!(cin >> num))
{
    cin.clear(); // Clear the error flag
    cin.sync(); // Clear out all the junk in the buffer
    cout << "Grr, why'd you do that?!\nTry again: ";
}

(or use strings and stringstreams)
@long double main, well, it could ask twice a user input, eventually asking for a number, but it would look silly then anyways.
It would like silly if you were asked to enter a number and you entered "five" instead of "5", and it would look even sillier if the program then procedded to fail. It would not look silly if the program caught you and asked you again.
Topic archived. No new replies allowed.