Search code examples
c++if-statementbooleanlogical-and

How to change a bool from true to false using an if statement that has user input as its condition?


Header file:

#include <iostream>
#include <string>

std::string correctText = "\nCorrect! +";
std::string incorrectText = "False!\n";
std::string answer = "paris";

bool correct = true;

int score;

void scoreSystem() {
    if (correct == true) {
        std::cout << correctText;
        score++;
    }
    else {
        std::cout << incorrectText;
    }
}

Source file:

#include <iostream>
#include <string>
#include "Primitive Quiz Header.h"

int main() {
    std::cout << "What is the capital of france?\n\n";
    if (std::cin >> answer) {
        correct = true;
    }
    else {
        correct = false;
    }
    scoreSystem();
    std::cout << score;
    return 0;
}

The code is intended to use the bool correct as a way to tell the scoreSystem() function if it should increment the score integer and output the string correctText, or output the incorrectText string. If the user answers correctly, correct should be true; false if answered incorrectly.

However, no matter what the user enters, correct remains true and the scoreSystem() always outputs with the correctText string and increments the score integer.

Example:

What is the capital of france?

gruh \\example of incorrect user input

Correct! +1

I don't understand what exactly is preventing correct from changing. Is it the scoreSystem() function, or how the user inputs their answer in main()?


Solution

  • A statement like if (x) y = true; is clumsy, and should generally be avoided. If x is already a bool, then you can usually use y = x;. If it's not already a bool, then you may want y = static_cast<bool>(x); instead (or, for people who prefer parsimony, y = !!x;).

    It's also rarely useful to ask only a single question. Usually you'd want something along this general line:

    struct Question {
        std::string question;
        std::string answer;
    
        bool correct(std::string const &user_answer) { 
           return user_answer == answer;
        }
    
        friend std::ostream &operator<<(std::ostream &os, Question const &q) { 
            return os << q.question;
        }
    };
    

    Then you could have a number of questions and answers, something like this:

    const std::vector<Question> questions { 
        { "What is the capitol of France?", "Paris" },
        { "what is the capitol of Great Britain?", "London"},
        { "What is deepest lake on earth?", "Baikal"}
        // ...
    };
    
    int main() { 
        int score = 0;
    
        for (auto const &q : questions) {
            std::cout << q;
            std::string user_answer;
            std::cin >> user_answer;
            bool correct = q.correct(user_answer);
            std::cout << std::boolalpha << correct;
            score += correct;
        }
        std::cout << "You got: " << score << " questions right\n";
    }
    

    This has one minor defect though. It prints out true and false instead of "\nCorrect! +" and "\nFalse!". Fortunately, there's a way to fix that too.

    #include <string>
    #include <vector>
    #include <locale>
    #include <ios>
    #include <iostream>
    
    class TestPunct : public std::numpunct< char > {
    protected:
        char do_decimal_point() const { return ','; }
        char do_thousands_sep() const { return '.'; }
        std::string do_grouping() const { return "\3"; }
        std::string do_truename() const { return "\nCorrect!\n";  }
        std::string do_falsename() const { return "\nFalse\n"; }
    };
    
    struct Question {
        std::string question;
        std::string answer;
    
        bool correct(std::string const &user_answer) const { 
           return user_answer == answer;
        }
    
        friend std::ostream &operator<<(std::ostream &os, Question const &q) { 
            return os << q.question << "? ";
        }
    };
    
    const std::vector<Question> questions { 
        { "What is the capitol of France", "Paris" },
        { "what is the capitol of Great Britain", "London"},
        { "What is deepest lake on earth", "Baikal"}
        // ...
    };
    
    int main() { 
        std::cout.imbue(std::locale(std::locale(), new TestPunct));
    
        int score = 0;
    
        for (auto const &q : questions) {
            std::cout << q;
            std::string user_answer;
            std::cin >> user_answer;
            bool correct = q.correct(user_answer);
            std::cout << std::boolalpha << correct;
            score += correct;
        }
        std::cout << "You got: " << score << " questions right\n";
    }
    

    Result:

    $ ./a.out
    What is the capitol of France? Paris
    
    Correct!
    what is the capitol of Great Britain? London
    
    Correct!
    What is deepest lake on earth? Baikal
    
    Correct!
    You got: 3 questions right