I made a C++ user input that detects when no value is being input, but it terminates the program on startup without outputting anything. Why?
#include <iostream>
int main() {
bool entered = false;
while(entered = false) {
std::cout << "Please enter thy name: ";
std::string name;
std::getline(std::cin, name);
std::cout << "Hello, " + name;
int length = name.length();
if(length > 0) {
std::cout << "Hello, " + name;
entered = true;
} else {
std::cout << "Thou did not enter thy name";
}
}
}
I already made a similar program in Java with a similar format and that one works fine.
This loop condition:
while(entered = false)
is wrong. Instead of comparing false and entered, you are assigning false to entered.
Instead, you need to do:
while(entered == false)
If you turn on warnings, for example with -Wall, the compiler will tell you that you are likely making a mistake here.
I can see that your main function starts with int but I can't see return 0, remember that if your function is not void then it must return something.
Related
So, let me preface that I am still learning C++ and would appreciate some guidance on what I am doing wrong.
My prompt is to write a function that continuously prompts a user for a valid age (between 0 and
100) and the function must only return the age to the caller of the function after a valid age is retrieved. AND For each function, you must declare the function using a function prototype before main and then define the function after main.
Here is my code,
#include <iostream>
using namespace std;
int num;
bool valid;
int validateInput()
{
cout << "Pick a number between 0 and 100" << endl;
cin >> num;
while(bool valid = false)
{
if(num <= 0)
{
cout << "Error: Number is invalid because it's too low" << endl;
bool valid = false;
return 0;
}
else if (num >= 100)
{
cout << "Error: Number is invalid because it's too high" << endl;
bool valid = false;
return 0;
}
else
{
cout << "You are " << num << " years old." << endl;
bool valid = true;
return 0;
}
}
}
int main()
{
validateInput();
return 0;
}
So I am trying to get my program to work but the IF statements keep getting skipped.
Am I misunderstanding something? Any and all help is very much appreciated.
EDIT: Thank you to Arvin and iammilind for your help.
I was able to fix the code so my while loop condition would actually trigger, moved my cout statements into the loop and so I wouldn't get infinite output.
My final working code looked like this.
#include <iostream>
using namespace std;
int num;
bool valid = false;
int validateInput()
{
while(!valid)
{
cout << "Pick a number between 0 and 100" << endl;
cin >> num;
if(num <= 0)
{
cout << "Error: Number is invalid because it's too low" << endl << endl;
bool valid = false;
}
else if (num >= 100)
{
cout << "Error: Number is invalid because it's too high" << endl << endl;
bool valid = false;
}
else
{
cout << "You are " << num << " years old." << endl;
bool valid = true;
return 0;
}
}
}
int main()
{
validateInput();
return 0;
}
You give a false value to the while loop that makes the while loop doesn't start the loop.
do this instead:
bool valid = false;
while (!valid){ // while valid is still false, do the loop
// your code here
}
Further explanation: You're currently using sentinel-controller loop
reference: https://simplecplusplus.wordpress.com/tag/sentinel-controlled-loop/
In order for while loop to start running, you've to provide the "true" condition to the while, and it will start looping until the condition turn out to false.
Programming tips for you: next time, you've to see the larger picture of your code every time you're trying to debugging. If you're sure the if-else code is running and have no problem, you have to enlarge your investigation for the bug, maybe it's the while loop that didn't work, not if-else. And if the while loop seems having no problem, maybe its the function or the caller of the function
while(bool valid = false) never allows the execution to enter the loop. Hence the if conditions are never called.
Use it as below:
while(valid == false) { // see '==' sign. `while(not valid)` is also fine
// ... your 'if' conditions
}
Actually you are creating a locally scope variable within while() by having a bool before it. So bool valid hides bool ::valid (declared outside).
Also, once the loop ends, you may want to reset it to false again. Otherwise this function will never be able to used again!
Using globals (bool valid) for such functionality is a bad design.
Please note that I am a complete beginner at C++. I'm trying to write a simple program for an ATM and I have to account for all errors. User may use only integers for input so I need to check if input value is indeed an integer, and my program (this one is shortened) works for the most part.
The problem arises when I try to input a string value instead of an integer while choosing an operation. It works with invalid value integers, but with strings it creates an infinite loop until it eventually stops (unless I add system("cls"), then it doesn't even stop), when it should output the same result as it does for invalid integers:
Invalid choice of operation.
Please select an operation:
1 - Balance inquiry
7 - Return card
Enter your choice and press return:
Here is my code:
#include <iostream>
#include <string>
using namespace std;
bool isNumber(string s) //function to determine if input value is int
{
for (int i = 0; i < s.length(); i++)
if (isdigit(s[i]) == false)
return false;
return true;
}
int ReturnCard() //function to determine whether to continue running or end program
{
string rtrn;
cout << "\nDo you wish to continue? \n1 - Yes \n2 - No, return card" << endl;
cin >> rtrn;
if (rtrn == "1" and isNumber(rtrn)) { return false; }
else if (rtrn == "2" and isNumber(rtrn)) { return true; }
else {cout << "Invalid choice." << endl; ReturnCard(); };
return 0;
}
int menu() //function for operation choice and execution
{
int choice;
do
{
cout << "\nPlease select an operation:\n" << endl
<< " 1 - Balance inquiry\n"
<< " 7 - Return card\n"
<< "\nEnter your choice and press return: ";
int balance = 512;
cin >> choice;
if (choice == 1 and isNumber(to_string(choice))) { cout << "Your balance is $" << balance; "\n\n"; }
else if (choice == 7 and isNumber(to_string(choice))) { cout << "Please wait...\nHave a good day." << endl; return 0; }
else { cout << "Invalid choice of operation."; menu(); }
} while (ReturnCard()==false);
cout << "Please wait...\nHave a good day." << endl;
return 0;
}
int main()
{
string choice;
cout << "Insert debit card to get started." << endl;
menu();
return 0;
}
I've tried every possible solution I know, but nothing seems to work.
***There is a different bug, which is that when I get to the "Do you wish to continue?" part and input any invalid value and follow it up with 2 (which is supposed to end the program) after it asks again, it outputs the result for 1 (continue running - menu etc.). I have already emailed my teacher about this and this is not my main question, but I would appreciate any help.
Thank you!
There are a few things mixed up in your code. Always try to compile your code with maximum warnings turned on, e.g., for GCC add at least the -Wall flag.
Then your compiler would warn you of some of the mistakes you made.
First, it seems like you are confusing string choice and int choice. Two different variables in different scopes. The string one is unused and completely redundant. You can delete it and nothing will change.
In menu, you say cin >> choice;, where choice is of type int. The stream operator >> works like this: It will try to read as many characters as it can, such that the characters match the requested type. So this will only read ints.
Then you convert your valid int into a string and call isNumber() - which will alway return true.
So if you wish to read any line of text and handle it, you can use getline():
string inp;
std::getline(std::cin, inp);
if (!isNumber(inp)) {
std::cout << "ERROR\n";
return 1;
}
int choice = std::stoi(inp); // May throw an exception if invalid range
See stoi
Your isNumber() implementation could look like this:
#include <algorithm>
bool is_number(const string &inp) {
return std::all_of(inp.cbegin(), inp.cend(),
[](unsigned char c){ return std::isdigit(c); });
}
If you are into that functional style, like I am ;)
EDIT:
Btw., another bug which the compiler warns about: cout << "Your balance is $" << balance; "\n\n"; - the newlines are separated by ;, so it's a new statement and this does nothing. You probably wanted the << operator instead.
Recursive call bug:
In { cout << "Invalid choice of operation."; menu(); } and same for ReturnCard(), the function calls itself (recursion).
This is not at all what you want! This will start the function over, but once that call has ended, you continue where that call happened.
What you want in menu() is to start the loop over. You can do that with the continue keyword.
You want the same for ReturnCard(). But you need a loop there.
And now, that I read that code, you don't even need to convert the input to an integer. All you do is compare it. So you can simply do:
string inp;
std::getline(std::cin, inp);
if (inp == "1" || inp == "2") {
// good
} else {
// Invalid
}
Unless that is part of your task.
It is always good to save console input in a string variable instead of another
type, e.g. int or double. This avoids trouble with input errors, e.g. if
characters instead of numbers are given by the program user. Afterwards the
string variable could by analyzed for further actions.
Therefore I changed the type of choice from int to string and adopted the
downstream code to it.
Please try the following program and consider my adaptations which are
written as comments starting with tag //CKE:. Thanks.
#include <iostream>
#include <string>
using namespace std;
bool isNumber(const string& s) //function to determine if input value is int
{
for (size_t i = 0; i < s.length(); i++) //CKE: keep same variable type, e.g. unsigned
if (isdigit(s[i]) == false)
return false;
return true;
}
bool ReturnCard() //function to determine whether to continue running or end program
{
string rtrn;
cout << "\nDo you wish to continue? \n1 - Yes \n2 - No, return card" << endl;
cin >> rtrn;
if (rtrn == "1" and isNumber(rtrn)) { return false; }
if (rtrn == "2" and isNumber(rtrn)) { return true; } //CKE: remove redundant else
cout << "Invalid choice." << endl; ReturnCard(); //CKE: remove redundant else + semicolon
return false;
}
int menu() //function for operation choice and execution
{
string choice; //CKE: change variable type here from int to string
do
{
cout << "\nPlease select an operation:\n" << endl
<< " 1 - Balance inquiry\n"
<< " 7 - Return card\n"
<< "\nEnter your choice and press return: ";
int balance = 512;
cin >> choice;
if (choice == "1" and isNumber(choice)) { cout << "Your balance is $" << balance << "\n\n"; } //CKE: semicolon replaced by output stream operator
else if (choice == "7" and isNumber(choice)) { cout << "Please wait...\nHave a good day." << endl; return 0; }
else { cout << "Invalid choice of operation."; } //CKE: remove recursion here as it isn't required
} while (!ReturnCard()); //CKE: negate result of ReturnCard function
cout << "Please wait...\nHave a good day." << endl;
return 0;
}
int main()
{
string choice;
cout << "Insert debit card to get started." << endl;
menu();
return 0;
}
This program is a very simple one, a guessing game, however the issue is that when I compile it, it displays no errors. When I run it, it does nothing. I have tried fixing it, in that I moved the code within the guess() function back into main, and that works, printing "Enter a number between 0 & 100: ". Then when you do enter a number, it freezes, and this is probably caused by the lack of stop condition for the recursion. As I am not returning integers, as main has to, I reverted back to using the guess() function, and I have no idea why it doesn't work.
#include <iostream>
#include <cstdlib>
#include <string>
int computer = rand() % 101;
int user = 0;
int counter = 0;
std::string guess();
int main(void) {
std::string guess();
return 0;
}
std::string guess() {
std::cout << "Enter a number between 0 & 100: ";
std::cin >> user;
if(!(std::cin >> user)) {
return "You entered a non-numeric. Try again. Tries will not be added.";
std::cin.clear();
std::cin.ignore(10000, '\n');
std::string guess();
}
else {
if(user == computer) {
std::cout << "You guessed the right number of " << computer << " in " << counter << " tries.\n";
}
else {
if(user < computer) {
return "The answer is higher. Try again.";
}
else if(user > computer) {
return "The answer is lower. Try again.\n";
}
counter++;
std::string guess();
}
}
}
Note that I am very much a novice programmer, and the issue is probably quite simple and obvious, but I just can't see it. Thanks.
The problem is, that your often write std::string guess(); in order to call your guess() method (e.g. in main. But that doesn't call the method. What it actually does is to declare a new function guess, which is never called (see also Most vexing parse). To only call the method simply write guess();, or auto result = guess(); if you actually want to use the return value.
Also there is an error in this part of your code (see comment):
if(!(std::cin >> user)) {
return "You entered a non-numeric. Try again. Tries will not be added.";
// the following lines are never executed, since you already returned.
std::cin.clear();
std::cin.ignore(10000, '\n');
std::string guess();
}
Issue
The issue is indeed simple and obvious:
std::string guess();
It's obvious that you would like to call your "guess" function, but instead you've just declared it inside "main" and inside "guess".
These declarations are similar to the declaration that you made on the next line after int counter = 0;. It tells compiler that if it encounters call to the function named "guess" it should know that it is a function that takes no arguments and returns std::string.
So, the issue is that instead of calling a function, you declared it several times;
Solution
When you want to call your function you should do it like this:
std::string result = guess();
But since you return some message from guess() I think you should add output after that:
std::cout << result << std::endl;
Actually, I think it would be better to remove return value altogether. In order to do that you should modify "guess" function in a following way:
change return type from std::string to void
replace return with std::cout <<.
Many mistakes.
Firstly you don't need string return type.
So change std::string guess() to void guess()
Then use cin.fail() instead of !(cin>>user)
Also use else if rather than
else{
if{
To generate random number, firstly intialize seed and that can't be done globally, so generate random number in main and pass it in guess function.
To summarize here is the code
#include <iostream>
#include <cstdlib>
#include <string>
#include<ctime>
int user = 0;
int counter = 0;
void guess(int computer);
int main(void) {
srand(time(NULL));
int computer = rand() % 101;
guess(computer);
return 0;
}
void guess(int computer) {
std::cout << "Enter a number between 0 & 100: ";
std::cin >> user;
//std::cout<<computer<<std::endl;
if(std::cin.fail()) {
std::cout<< "You entered a non-numeric. Try again. Tries will not be added.";
std::cin.clear();
std::cin.ignore(10000, '\n');
guess(computer);
}
else if(user == computer) {
std::cout << "You guessed the right number of " << computer << " in " << counter << " tries.\n";
return;
}
if(user < computer) {
std::cout<< "The answer is higher. Try again.\n";
}
else if(user > computer) {
std::cout<< "The answer is lower. Try again.\n";
}
counter++;
guess(computer);
}
Completely new to C++. Trying to understand classes and objects, so far I get the gist of it, as it's nothing too complicated for the very basics. However, this code I have wrote is not working as intended. It works somewhat, however it asks for user input twice.
#include <iostream>
#include <string>
using namespace std;
class FooFoo {
public :
string GetName() {
cin >> name;
return name;
}
private:
string name;
};
int main()
{
FooFoo object;
if (object.GetName() == "John" || object.GetName() == "Chris")
{
cout << "Yes";
}
else {
cout << "No";
}
}
If I input "John", it will return yes right away. However, when I input anything else, it will prompt me to enter something again, and then the if/else acts accordingly to whatever I inputted.
You call object.GetName() twice which causes the input to be asked for twice. Store the result of this function to a variable and use that in the if statement. The || statement is short-circuited if the first expression is true. This leads to the second call not being executed if the first is true.
That is because GetName() is asking for input every time,
So the first time it is asking for x, if x isnt john it goes to the next test, which then gets input and tests that against x = chris.
try changing it to this:
int main()
{
FooFoo object;
string test = object.GetName()
if (test == "John" || test == "Chris")
{
cout << "Yes";
}
else {
cout << "No";
}
}
Hope that helps
Your current if statement effectively evaluates to:
if (object.GetName() == "John")
cout << "Yes";
else if (object.GetName() == "Chris")
cout << "Yes";
else
cout << "No";
Try entering Chris followed by John and you should get No.
Just call getName() before the if statement, store the value in a local variable, then test that instead:
string name = object.GetName();
if (name == "John" || name == "Chris")
cout << "Yes";
else
cout << "No;
I started learning some basics of C++ and I wanted to write some code to practices what I've learned. I wanted to make a class and some functions. It's supposed to be a title screen to start a text game, except there is no game...yet :P
Whenever I enter 1 to start so it displays "Good Work" it just does nothing after I hit enter.
Any point in the right direction would be great. I've been watching videos and reading tutorials on functions, it doesn't seem to cover the problem I'm having...
#include <iostream>
#include <string>
using namespace std;
//Function Protos
void keyError();
int userInput(int x);
//class library
class Title
{
bool nSelect;
int x;
public:
void titleScreen()
{
while(nSelect)
{
cout << "Welcome to Biggs RPG!" << endl << "1. Play 2. Exit" << endl;
userInput(x);
if (userInput(1))
nSelect = 0;
else if (userInput(2))
{
cout << "Closing program..." <<endl;
nSelect = 0;
}
else
keyError();
}
}
};
int main()
{
Title displayTitle;
displayTitle.titleScreen();
cout << "Good work";
return 0;
}
void keyError()
{
cout << "Meow? Wrong input try again." << endl;
}
int userInput(int x)
{
x = 0;
cin >> x;
return x;
}
There are numerous stylistic and technical problems. Try learning from resources recommended in The Definitive C++ Book Guide and List.
Here is a start…
#include <iostream>
#include <string>
// "using namespace std;" is poor practice. Better to write out std::
/* Unless you will have two title screens at the same time,
this should probably be a namespace, not a "singleton" class. */
namespace Title
{
int nSelect;
void titleScreen()
{
do {
// prompt for input
std::cout << "Welcome to Biggs RPG!\n" "1. Play 2. Exit\n";
// get ready to accept input, even if there was an error before
if ( ! std::cin ) {
std::cin.clear(); // tell iostream we're recovering from an error
std::cin.ignore( 1000, '\n' ); // ignore error-causing input
}
// repeat if invalid input
} while( ! std::cin >> nSelect || ! handleInput( nSelect ) );
The difference is that you want to ask for input, then handle it. The code you posted asks for input again each time it checks what the input was.
This is a do … while loop, so it executes at least once and then repeats as long as the condition at the end is true. If the user gives an invalid input, then ! std::cin evaluates to true. Then the policy of C++ is to stop returning any input until you call std::cin.clear(), which signals that you are going to try again. ignore then gets rid of the invalid input. Then ! std::cin >> nSelect tries to read a number, and if that operation is successful, call handleInput (which you must write) which should return false if the input was invalid. So if reading a number fails, or the wrong number was entered, the loop goes again.
You should compare the return value of userInput with 1 or 2, like this:
int userInput(void);
//class library
class Title
{
bool nSelect;
int x;
public:
void titleScreen()
{
nSelect = true;
while(nSelect)
{
cout << "Welcome to Biggs RPG!" << endl << "1. Play 2. Exit" << endl;
x = userInput();
if (x == 1)
nSelect = false;
else if (x == 2)
{
cout << "Closing program..." <<endl;
nSelect = false;
}
else
keyError();
}
}
};
and define userInput as:
int userInput(void)
{
int x = 0;
cin >> x;
return x;
}
I sense confusion about the difference between parameters and return values. When you define a function as
int userInput(int x) {
...
You pass a value to the function (x) and return a value with the return statement. In your case you don't need to pass a parameter to your function; you need to return a value. You access this value by assigning it to another variable:
theResult = userInput(123);
But it doesn't matter what value you pass to the function; you might as well use
int userInput(void) {
...
In which case you can use
theResult = userInput();
Now just to confuse you, it is possible to pass the address of a variable as a parameter to a function. You can use that either to access data (usually a "larger" block of data like an array or struct) but it can also be used to provide a place where a return value is stored. Thus
void squareMe(int *x){
*x*=*x;
}
Would return the square of the number pointed to in that location. You could then do
int x=4;
squareMe(&x);
cout << x;
Would print out 16 (!). This is because the function looks at the contents of the address (&x is the address of the variable x), and multiplies it by itself in- place.
I hope this explanation helps.