0

I'm extremely new to C++, and can't really figure this out. I've tried a couple things, but I feel like I'm just missing something simple.

I have this console application where a user inputs a pre-defined password. If the password is incorrect, it prompts them to re-enter the password. If the password is correct, is simply ends the program, but I want it to say "Access granted!" then end.

A side issue I'm having is when more than word is entered as the password, "Access Denied" is printed for each word.

string password;

cout << "Please enter the password!" << endl;
cin >> password;

if (password == "test") {
    cout << "Access granted!";
} else {
    do {
        cout << "Access denied! Try again." << endl;
        cin >> password;
    } while (password != "test");
}

return 0;
jww
  • 97,681
  • 90
  • 411
  • 885
Bellator
  • 352
  • 1
  • 3
  • 11
  • 2
    You need to move your `if / else` logic inside the loop. – πάντα ῥεῖ May 01 '19 at 18:06
  • See this question about why `cin` only reads one word: https://stackoverflow.com/questions/9469264/c-cin-only-reads-the-first-word (and also note that `std::string` is much better and safer to use than a raw `char` array) – alter_igel May 01 '19 at 18:07
  • @πάνταῥεῖ Are you going to create an answer? – Yunnosch May 01 '19 at 18:08
  • Please only ask one question. Cramming two questions in makes this too broad. Start with the loop logic and the desired output. Aks about multiple word misbehaviour later. – Yunnosch May 01 '19 at 18:09
  • 1
    Moving `"cout << "Access granted!";` to after the loop would be the simplest change. – François Andrieux May 01 '19 at 18:10
  • @FrançoisAndrieux This does work, but is there a more cleaner solution? As you said, this is the simplest, but I am up for a challenge. – Bellator May 01 '19 at 18:13
  • @πάνταῥεῖ This unfortunately did not change the outcome of the loop. – Bellator May 01 '19 at 18:13
  • @CelticTree Well, that was only a nudge (thus a comment), never said it would fully solve your problems. – πάντα ῥεῖ May 01 '19 at 18:15
  • 1
    @CelticTree It's quite a simple project with simple goals and no apparent constraints. So the solution is also likely to be simple. It's not likely to be challenging. In addition, simpler is usually cleaner. Asking for a cleaner solution is usually contrary, in principal, to asking for a more challenging solution. – François Andrieux May 01 '19 at 18:17
  • @FrançoisAndrieux Ah, well this makes sense. I'm just fairly new to C++ and going in, I expected everything to be hard. It's all coming together quite nicely though. – Bellator May 01 '19 at 18:24
  • @CelticTree The basic rules and syntax of c++ aren't very easy, but they aren't as hard as people make them out to be. The *real* challenge is that, unlike most other languages, c++ has Undefined Behavior. It's possible (and easy) to accidentally write code that is illegal but that the compiler won't warn you about. In that case, your code can do anything at all. As such, it's not possible to learn c++ by trial-and-error. Observing that code has a certain behavior isn't enough to prove that the behavior is required or that it will be consistent. You need to know and internalize the rules. – François Andrieux May 01 '19 at 18:33
  • @CelticTree I'll congratulate because it doesn't appear that you've picked up many of the bad habits new c++ developers usually pick up (though you might have used `using namespace std;` here, can't tell). Be sure that, to continue on this promising trend, you make sure any material you use to further learn c++ is *actually* for c++ and not for c. A lot of new developers learn from c and c++ resources, but best practices in c are often considered bad behavior in c++. In addition, try to focus on more recent resources, as the language has changed **drastically**, specially since 2011. – François Andrieux May 01 '19 at 18:36
  • @FrançoisAndrieux Thank you for your wisdom. And unfortunately, I was using `namespace std` when I first started (yesterday), but I've read about why it's bad practice. It can lead to conflicting elements in the future. Do you have any sources you'd recommend? I've been learning from a basic site that pretty much teaches syntax, functions, loops, etc. I know all of these things from my knowledge in PHP though. – Bellator May 01 '19 at 18:54
  • @CelticTree Sorry to say I haven't kept up to date on the best self-teaching material. Anything I would have used is surely out of date by now. Be on the lookup for terms such as c++17 (or c++11 and c++14). There's a new version every 3 years since c++11. You'll be sure that the content is relevant. For reference purposes, use https://en.cppreference.com. It's very complete and widely considered to be reliable and correct. Though, it isn't simplified like some other sites, so some topics can be tricky to look up at first. But, it may be best to get used to it early. – François Andrieux May 01 '19 at 18:59

1 Answers1

2

You need to output your "Access granted" message after the loop exits, and you also need to clear the stdin input after each failed attempt to discard any words that are still waiting to be read:

#include <limits>

string password;

cout << "Please enter the password!" << endl;
cin >> password;

if (password == "test") {
    cout << "Access granted!";
} else {
    do {
        cin.clear();
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
        cout << "Access denied! Try again." << endl;
        cin >> password;
    } while (password != "test");
    cout << "Access granted!";
}

return 0;

Live Demo

Which would be better written like this instead:

#include <limits>

string password;

cout << "Please enter the password!" << endl;
do {
    cin >> password;
    cin.clear();
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
    if (password == "test") break;
    cout << "Access denied! Try again." << endl;
}
while (true);

cout << "Access granted!";
return 0;

Live Demo

However, note that operator>> reads only 1 word at a time, so something like "test I GOT IN!" will also be accepted. You should use std::getline() instead to read an entire line at a time, instead of reading a word at a time:

#include <limits>

string password;

cout << "Please enter the password!" << endl;
do {
    getline(cin, password);
    if (password == "test") break;
    cout << "Access denied! Try again." << endl;
}
while (true);

cout << "Access granted!";
return 0;

Live Demo

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Thank you! This simultaneously answered both of my questions. And the solution was quite simple indeed, but I'm not sure if I ever would've figured it out. A side error is that if "test" is the first word in the string, it still accepts it even if other things follow. But I will figure this one out on my own, thank you for the help! – Bellator May 01 '19 at 18:21
  • 1
    That is because `operator>>` only reads one word at a time. Use `std::getline()` instead to read a line at a time instead. – Remy Lebeau May 01 '19 at 18:42