Bug Busting (involves a switch, cin.getline)

Alright so I have this code which is beginning to simulate the Descent Character Creator, where at the end I give the option to return to a previous 'step' (choose name, race, change stats etc.) only I'm having trouble returning to Step 1, Name Change.

I have a switch(progress), where each 'step' is a separate case. It looks something like this:

int progress = 1;

case 0:
// Terminate Program code
break;

case 1:
// Call 'NewScreen' (function to system("cls"), cout text, progress++)
// Choose name (char pName[50])
break;

case 2:
// Call 'NewScreen'
// Choose race, assign its stats
break;

case 3:
// Call 'NewScreen'
// Currently, gives option to return to a previous 'step'
break;


The problem:

When you get to case 3, every choice works besides 1. 0 will end the program, 2 will return to the race selection, 3 will return to itself. However, if you choose 1 and enter, it flashes to the name entry screen then immediately continues to case 2, where the name is "" (nothing).

I'm not even sure how to check for errors here, I think it has something to do with the cin.getline(49, pName) thing being used more than once or something. Anyway, help will be much appreciated.


Full Code:

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
    #include <iostream>
    #include <cstdlib>
    #include <windows.h>

    using namespace std;


    // Text Colour:
    enum Colour  { blue = 1, green, cyan, red, purple, yellow, grey, dgrey, hblue, hgreen, hcyan, hred, hpurple, hyellow, white };

    void coutc(int color)
    {
        HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleTextAttribute(handle, color);
    }


    // Prototypes:
    void NewScreen();
    void ShowStats(string text, int stat);


    // Global Variables:
    bool EndProgram = false;
    char pName[50];
    int wounds,
        fatigue,
        armour,
        speed,
        points,
        progress = 1;


    // Main:
    int main()
    {
        int race;

        string name[5] = { "Human", "Bestial", "Dwarven", "Elven", "Nimble" };

        while(EndProgram == false)
        {
            switch(progress)
            {
                // - - - - - - - - - - - -
                case 0: // Exit Program
                // - - - - - - - - - - - -

                    cout << "\n\n\tEnding Program.\n\n";
                    EndProgram = true;

                    break;

                // - - - - - - - - - - - -
                case 1: // Choose a Name
                // - - - - - - - - - - - -

                    NewScreen();

                    cout << "Name: ";
                    cin.getline(pName, 49);

                    break;

                // - - - - - - - - - - - -
                case 2: // Choose a Race
                // - - - - - - - - - - - -

                    while(true)
                    {
                        NewScreen();

                        cout << "Select a race:\n\n\t";

                        // List Races:
                        for(int i = 0; i <= 4; i++)
                        {
                            cout << i+1 << ") " << name[i] << "\n\t";
                        }

                        cout << "\n\t-- ";

                        cin >> race;

                        // Check Selection:
                        if(race < 1 || race > 5){
                            progress--;
                        } else {
                            break;
                        }
                    }

                    // Race Base Stats:
                    switch(race)
                    {
                        case 1:
                        wounds  = 12;
                        fatigue = 4;
                        armour  = 1;
                        speed   = 4;
                        points  = 12;
                            break;
                        case 2:
                        wounds  = 16;
                        fatigue = 4;
                        armour  = 0;
                        speed   = 4;
                        points  = 10;
                            break;
                        case 3:
                        wounds  = 8;
                        fatigue = 5;
                        armour  = 2;
                        speed   = 3;
                        points  = 10;
                            break;
                        case 4:
                        wounds  = 8;
                        fatigue = 4;
                        armour  = 1;
                        speed   = 5;
                        points  = 10;
                            break;
                        case 5:
                        wounds  = 8;
                        fatigue = 5;
                        armour  = 0;
                        speed   = 4;
                        points  = 15;
                            break;
                    }

                    break;

                // - - - - - - - - - - - -
                case 3: // Print Stats
                // - - - - - - - - - - - -

                    NewScreen();

                    ShowStats("Wounds:  ",  wounds);
                    ShowStats("Fatigue: ", fatigue);
                    ShowStats("Armour:  ",  armour);
                    ShowStats("Speed:   ",   speed);
                    ShowStats("Points:  ",  points);

                    // PLACEHOLDER SET PROGRESS
                    cout << "\n\tPlease set progress: ";
                    cin >> progress;

                    break;

                // - - - - - - - - - - - -
                case 4: // Modify Stats
                // - - - - - - - - - - - -

                    NewScreen();

                    //...
                    break;
            }
        }
    }


    // NewScreen:
    void NewScreen()
    {
        /* ClearScreen:      */ system("cls");
        /* SetHeaderColour:  */ coutc(cyan);
        /* SetHeaderText:    */ cout << "\n\n\t:: DESCENT: Character Creator :: " << progress << " ::\n\n\t";
        /* SetDefaultColour: */ coutc(white);

        // Re-print New Information:
        if(progress >= 2){
            cout << "Name: " << pName << "\n\n\t";
        }

        progress++;
    }


    void ShowStats(string text, int stat)
    {
        coutc(dgrey);
        cout << " | ";
        cout << text;

        if(stat == 0 || (stat == wounds && wounds == 8)){
            coutc(red);
        } else {
            coutc(white);
        }

        if(stat < 10){
            cout << " ";
        }

        cout << stat;
        coutc(dgrey);
        cout << " |\n\t";
        coutc(white);
    }
Last edited on
Basically, to make a complicated concept short, it is not a good idea to mix "cin.getline" and "cin >>" in the same program.

In your "Progress 1" section you have:

1
2
                    cout << "Name: ";
                    cin.getline(pName, 49);


but when you set progress, you obtain it like:
1
2
3
                    // PLACEHOLDER SET PROGRESS
                    cout << "\n\tPlease set progress: ";
                    cin >> progress;


This can create problems. A very long explanation of the issue is here: http://www.daniweb.com/software-development/cpp/tutorials/90228

One option:

Change

1
2
                    cout << "Name: ";
                    cin.getline(pName, 49);


to
1
2
                   cout << "Name: ";
                    cin >> pName;


Of course, "cin >>" and "cin.getline" work a little differently, but I think this should work okay.
Last edited on
I used cin originally, but the problem with it is that if you enter anything other than a single string of letters (so spaces, symbols) it breaks the program.

I'm more trying to solve this for the experience than the actual outcome. I could easily just move the naming step right the way to the end of the program after the confirmation of stat changes etc, but then I wouldn't have solved this problem.
Last edited on
why not use string and getline (cin, var_name)
when your picking your race it will subtract progress however it will keep on doing that until you enter correctly so progress could be -5 before you get it right
Topic archived. No new replies allowed.