Murteira
Murteira

Reputation: 21

Cin isn't waiting for input

This is the program:

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


using namespace std;

int main(){


string strKingdom = "";
bool conquered_me;//see if was conquered, was going to use this on other program and true = game over.
int gold;
int food;
int citizens;
int soldiers;



cout << endl <<"Name of kingdom: ";
cin >> strKingdom;
cout << endl << "were you conquered (true/false): ";
cin >> conquered_me;
cout << endl << "How many gold do you have?:";
cin>>gold;
cout << endl << "How many food do you have?:";
cin >> food;
cout << endl << "How many citizens do you have?:";
cin >> citizens;
cout << endl << "How many soldiers do you have?:";
cin >> soldiers;


return 0;
}

The problem is that when I compile it the progam only lets me insert the first 2 variables and then it shows the rest of the questions (after compile):

Name of kingdom: steve

were you conquered (true/false): false

How many gold do you have?: How many food do you have?: How many citizens do you have?: How many soldiers do you have?:

Upvotes: 1

Views: 3210

Answers (6)

nsilent22
nsilent22

Reputation: 2863

Entering string "true" to the bool variable does not work. You should enter 1 or 0. Your "true" cannot be "consumed", so it's left in the buffer. Next, you're trying to read int value, so "true" also does not match. And so on... until the end of the program.

That's how I would do that:

#include <string>
#include <iostream>

#include <errno.h>
#include <stdlib.h>

using namespace std;

void askForString(string aPrompt, string &aValue) {
    cout << aPrompt << " ";
    cin >> aValue;
}

void askForBool(string aPrompt, bool &aValue) {
    string tString;
    while (1) {
        cout << aPrompt << " ";
        cin >> tString;
        if (tString == "true") {
            aValue = true;
            break;
        } else if (tString == "false") {
            aValue = false;
            break;
        } else {
            cout << "Repeat, please?" << endl;
        }
    }
}

void askForInt(string aPrompt, int &aValue) {
    string tString;
    char *endptr;
    while (1) {
        cout << aPrompt << " ";
        cin >> tString;
        errno = 0;
        aValue = strtol(tString.c_str(), &endptr, 10);
        if (errno || tString.c_str() == endptr || (endptr != NULL && *endptr != 0)) {
            cout << "Repeat, please?" << endl;
        } else {
            break;
        }
    }
}

int main(void) {
    string strKingdom;
    bool conquered_me;
    int gold;
    int food;
    int citizens;
    int soldiers;

    askForString("Name of kingdom:", strKingdom);

    askForBool("were you conquered (true/false):", conquered_me);

    askForInt("How many gold do you have?:", gold);

    askForInt("How many food do you have?:", food);

    askForInt("How many citizens do you have?:", citizens);

    askForInt("How many soldiers do you have?:", soldiers);

    cout << "Kingdom: " << strKingdom << endl;
    cout << "Conquered: " << (conquered_me ? "true" : "false") << endl;
    cout << "Gold: " << gold << endl;
    cout << "Food: " << food << endl;
    cout << "Citizens: " << citizens << endl;
    cout << "Soldiers: " << soldiers << endl;

    return 0;
}

Upvotes: 7

Lilith Daemon
Lilith Daemon

Reputation: 1473

You need to employ std::getline and std::string to read the various values. (You can then use functions like atoi to parse them.) Here is your code sample using the std::getline function.

#include <iostream>
#include <string>
#include <cstdlib>

int main(){


std::string strKingdom = "";
bool conquered_me;//see if was conquered, was going to use this on other program and true = game over.
int gold;
int food;
int citizens;
int soldiers;

std::string tString = ""; // Used to read and subsequently parse the string.


std::cout << std::endl <<"Name of kingdom: ";
std::getline(std::cin,strKingdom);

std::cout << std::endl << "were you conquered (true/false): ";
std::getline(std::cin,tString);
conquered_me = (tString == "true");

std::cout << std::endl << "How many gold do you have?:";
std::getline(std::cin,tString);
gold = std::atoi(tString.c_str());

std::cout << std::endl << "How many food do you have?:";
std::getline(std::cin,tString);
food = std::atoi(tString.c_str());

std::cout << std::endl << "How many citizens do you have?:";
std::getline(std::cin,tString);
citizens = std::atoi(tString.c_str());

std::cout << std::endl << "How many soldiers do you have?:";
std::getline(std::cin,tString);
soldiers = std::atoi(tString.c_str());


return 0;
}

Upvotes: 0

Jerry Coffin
Jerry Coffin

Reputation: 490108

For some reason (probably compatibility with older code) iostreams default to converting true to 1 and false to 0 during I/O.

That's only the default though--there's a manipulator named boolalpha that will set the stream to use true and false (or localized equivalents) instead.

So, code like:

std::cout << 1 == 0;               // produces `0`
std::cout << boolalpha << 1 == 0;  // produces `false`

This also works for input, so you can change your code to something like this:

cin >> boolalpha >> conquered_me;

...and it should work as expected (and in: it should accept inputs of false or true, and produce values of false and true from them, and if it doesn't that's bug in the standard library).

Upvotes: 2

sbabbi
sbabbi

Reputation: 11181

This line:

cin >> conquered_me;

Should be like this:

cin >> boolalpha >> conquered_me;

Otherwise the input expects either a "0" or a "1".

By using boolalpha your input can be "true" or "false.

Upvotes: 1

Chris Dodd
Chris Dodd

Reputation: 126193

None of your read commands check for error. ALL of them should be written as something like:

while (!(std::cin >> strKingdom)) {
    std::cerr << 'Bad input' << std::endl;
    std::cin.clear();  // clear the error
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // ignore the rest of the line
    // output the same prompt again?
}

To make this easier, you might want to write a helper function:

template<typename T> void get_input(const char *prompt, T &result) {
    std::cout << prompt << std::endl;
    while (!(std::cin >> result)) {
        std::cerr << 'Bad input' << std::endl;
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        std::cout << prompt << std::endl; } }

You can then specialize that for bool types to read true/false properly...

Upvotes: 1

donjuedo
donjuedo

Reputation: 2505

Bring them all into strings, and convert as needed.

Upvotes: 2

Related Questions