Just started C++ at university so I've decided to try and do a classic 'shop project' using C++.
I'm just wandering if there is any way to repeat an if statement from the else. For example in the code I'm asking the user if the would like help browsing the shop and if they reply yes then it shows them the options, if they reply no then it continues with the code, however if it isn't yes or no then the code tells the user it can't understand the user.
What I am asking is can I get the user to input the value again and it re-run the if statement without using a loop, or do I have to use a loop?
Here's the bit of code:
cin >> help;
if (help == "Yes" || help == "yes")
{
cout << "These are out current sections that you are able to browse:" << endl;
cout << "-Offers and Deals (1) \n-Computing (2) \n-Console (3) \n-Audio (4) \n-Electronic Displays (5) \n-Cabling (6) \n-General Accessories (7)" << endl;
}
else if (help == "No" || help == "no")
{
cout << "You have chosen not to look at our browsing list." << endl;
}
else
{
cout << "Sorry the system does not understand what you have entered. \n Please use full English (Yes/No)." << endl;
}
If anyone could help me with this, that would be great.
I know its simple code and probably a lot more efficient ways of doing it, just using the ways ive currently been taught at university so far.
Thank in advance.
without using a loop, or do I have to use a loop?
There are ways of achieving this without using a loop, but a loop is exactly the construct that allows you to repeat a block of code while a condition is true.
This explicitly expresses your intent and achieves the result you desire.
void menu()
{
while (true)
{
int i; std::cin >> i;
if (i == 0) { action0(); }
else if (i == 1) { action1(); }
else if (i == 2) { break; /* Return to caller */ }
else { /* Invalid selection, retry */ }
}
}
Another reasonable solution uses recursion. Example:
void menu()
{
int i; std::cin >> i;
if (i == 0) { action0(); }
else if (i == 1) { action1(); }
else if (i == 2) { return; /* Return to caller */ }
else { menu(); /* Invalid selection, retry */ }
}
However, this can have several drawbacks compared to a loop. Quoting François Andrieux from the comments:
Recursion is a reasonable alternative if loops can't be used, but it's worth mentioning the drawbacks. For example, there may be a limit to the number of times you can recur if tail call optimization doesn't come into play. If it does, then you essentially have a hidden loop. It's also worth mentioning that you can't do this with main. It's a mistake many beginners make when they first discover recursion.
Related
So, I'm triying to learn c++ (coming from python), and I wanted to make a program just to see if i could do it with what i've learned, here's the code
#include <iostream>
using namespace std;
int response(string i) {
if (i == "yes" or i == "Yes") {
cout << "\nHello, sad, I'm dad\n";
return(0);
}
else if (i == "no" or i == "No") {
cout << "Good for you pal\n";
return(0);
}
else {
cout << "Answer properly you overgrown flatworm\n";
response(i);
};
};
int main() {
string i;
cout << "Are you sad?";
cin >> i;
response(i);
};
Pretty simple huh? No. For some reason, yes and no answers work fine, but when I try something different I get insulted infinitely and the program crashes from exceeding it's memory limit. How do I solve this?
(English is not my native language, so feel free to correct any ortography mistakes)
At no point do you request further input. For bad input 'i', the response routine prints out an insult, and then calls itself with exactly the same string.
The response routine prints out an insult, and then calls itself with exactly the same string.
The response routine prints out an insult, and then calls itself with exactly the same string.
…
You need to allow the user to enter a new string, and then (if you want to use recursion) make the recursive call to validate the new input.
But as mentioned in the comment, this is not really a problem that needs a recursive solution.
This can be solved by eliminating recursion ad it involves moving the input routine inside of a function that's more self-contained:
int getResponse(string i) {
for(;;) {
string i;
cout << "Are you sad?";
cin >> i;
if (i == "yes" or i == "Yes") {
cout << "\nHello, sad, I'm dad\n";
return(0);
}
else if (i == "no" or i == "No") {
cout << "Good for you pal\n";
return(0);
}
else {
cout << "Answer properly you overgrown flatworm\n";
}
}
}
You have 2 issues:
In the else case, you are not asking for new user input.
You need to return the result of calling response(i), otherwise the code invokes undefined behavior.
else {
cout << "Answer properly you overgrown flatworm\n";
cin >> i;
return response(i);
};
Alternatively, since you never use the return value from response, you can just remove all the return statements, and make it a void function.
If you insist on using recursion then move the input and the check in the same function response() - that function doesn't need to return int at all. In main you can just call response().
void response()
{
string i;
cout << "Are you sad?";
cin >> i;
if (i == "yes" or i == "Yes")
{
cout << "\nHello, sad, I'm dad\n";
}
else if (i == "no" or i == "No")
{
cout << "Good for you pal\n";
return;
}
else
{
cout << "Answer properly you overgrown flatworm\n";
response();
}
}
int main()
{
response();
}
so that's my first time learning a language , and I was really excited to play with classes, i do have one major problem which i cant seem to understand ;
im building a bank menu . its a class ofcourse, and i have a different class of clients which is basicly an array in my bank.
so my menu function inside the bank looks like that :
void menu (){
manager();
int n,m;
cout << "welcome to our bank managment system. \n";
cout << "please choose one of the following options : \n";
cout << "1-add a new client\n";
cout << "2-remove a leaving client\n";
cout << "3-bank statistics\n";
cout << "4-if you are a costumer\n";
cout << "5-exit\n";
cin >> n ;
if()
if()
if()
if()
if()
note that my return function is been summoned a lot inside
i have a return function to go back to the menu :
void returnfunction (){
int back = 0;
cout << "\n0-back to menu \n press a diffrent number back to exit :)\n";
cin >> back ;
if (back==0){
return menu();
}
if (back!=0){
cout << "thank you for using our program ! ";
return ;
}
it is working perfect until i play with it to much , and then hit 5 to exit (that's my option for n==5)
i must emphasize that when im hitting 5 only after few simple actions its working fine...
how can i fix that return function ?
ofcourse my main looks like that :
int main()
{
srand (time(NULL));
Bank b ;
b.menu();
}
appricate all of your wisom , thanks a lot
Your function:
void returnfunction ()
is declared to return nothing (void) but you:
return menu();
do return something, that's very unclear (even though menu() returns void too)
If you want to call menu() and then return write:
menu();
return;
There are a couple problems with this code, and honestly it wouldn't compile in other imperative OO languages. But this is c++ where the rules don't matter. Aside: If you don't have a strong reason to be using C++, learn Rust first. I promise you'll thank me later.
Paul has the right of it. The compiler should error out at that statement:
return menu();
However the equivalent is perfectly legal:
menu();
return;
But this still will cause problems in theory (but maybe not in practice) because your function is almost, but not, a candidate for tail recursion optimisation. More here Which, if any, C++ compilers do tail-recursion optimization?
This becomes a problem when users return to the menu many times, it depletes your programs memory, eventually leading to a stack overflow fault. The common pattern you'll find in most every GUI / Graphics library is that of a main-loop. Something like:
int main() {
bool exit = false
while(!exit) {
int action = menu()
switch(action) {
case EXIT_SELECTION: exit = true; break;
case SHOW_STATISTICS: printStats(); break;
}
}
}
Each time you call a function, your program has to use more memory to keep track of everything related to that function call. Ordinarily this memory is released once a function ends, but because your menu function calls another function that calls your menu function that calls another function... and on and on, you will eventually run out of memory from all of the function calls since these functions cannot terminate until the functions they call terminates -- and thus your program will crash. The solution is to use a while loop and check the user's input for an exit code as a previous responder mentioned. It can look something like:
`void menu() {
char choice= '\0';
while(choice!= 3) {
std::cout << "Welcome to the menu!";
std::cout << "\t Option 1 \n";
std::cout << "\t Option 2 \n";
std::cout << "\t Option 3 \n";
std::cout << "Your option: ";
std::cin >> choice;
if(choice == 1) { /*do something*/ }
else if(choice == 2) { /*do something else*/ }
else if(choice == 3) { /*print a message and exit*/ }
else { /*bad choice -- try again*/ }
} //end while-loop
} //end menu()`
Also, notice that your functions' return types are void, which, by definition, cannot have any sort of return. C++ will allow you to say return; inside of a void function, but it is merely a way to escape the function right then and there and is not really intended to do anything more than that. Using return in any other way when working with void functions is confusing and runs a risk of causing big issues.
I'm relatively new to C++ (and programming in general for the most part) and I'm taking an online course which follows along by teaching with the aim of building a game. In one of the console application projects we have to write code which asks the user if the user wants play the game again.The goal for that part of the program is to ask the user to reply by typing "y" or "n" only and re-ask the question if the user responds by doing something else.
I have attempted to write code which does this and as far as I can see the code works fine. My question is, is the code I wrote valid in the following sense:
Will the code successfully accomplish the outlined task?
Is code like this prone to more errors if it grows later?
The code I have follows. In the main function:
.
.
.
do
{
PlayGame();
}
while (AskToPlayAgain());
And the function definition for AskToPlayAgain along with an apt description:
bool AskToPlayAgain()
{
bool Play = true;
string response = "";
cout << "Would you like to play again? y/n... ";
getline(cin, response);
if (response == "y") { }
else if (response != "n")
{
cout << "Please enter a valid response." << endl;
// We want AskToPlayAgain called again to ask for a proper response again; however,
// just calling it outside a conditional will cause the current "Play" value to be returned.
// This value is true by default and this function will return it even if "n" is entered after
// an invalid response. As such, in this case, we want this function to be called in the event
// of an invalid response which will always happen and we don't want the return value of the nested
// AskToPlayAgain function to be returned, which is true by default unless the program has successfully exited.
// Furthermore, once the nested AskToPlayAgain returns false, we want the program to exit and not return the "Play"
// (which is set to true) by the higher level AskToPlayAgain.
if (AskToPlayAgain()) { }
else { return false; }
}
else
{
Play = false;
cout << "Thank you for playing! :D" << endl;
}
return Play;
}
Is the reasoning I presented in the code comments valid? Is there a test case where this would fail? I've tried a few test cases, but all of them worked.
Many thanks for any help on this!
There is nothing wrong with your recursive method but you can simplify this with a loop, and avoid the potential problems associated with recursion. Loops and recursion are closely related. if (response == "y") { } is not wrong but it's an odd programming practice. If you are not going to do anything upon reaching this condition then don't bother testing for it.
Another method with while loop:
bool AskToPlayAgain()
{
while(true)
{
string response;
cout << "Would you like to play again? y/n... ";
getline(cin, response);
if(response == "y")
{
return true;
}
else if(response == "n")
{
cout << "Thank you for playing! :D" << endl;
return false;
}
cout << "Please enter a valid response." << endl;
}
}
Edit
Another example with recursive function:
This time we add a counter value for demonstration.
If you run this program and keep giving invalid input, then counter will go up. It shows how the recursive function needs to wait for all other recursive functions to finish.
I added char buf[1000] which is not used. Its purpose is to cause problems!
Potential problem: each function needs to allocate 1000 bytes stack memory (plus memory for other stack variables in the function, and heap memory for std::string). This memory is not freed until the function exists, so it builds up. Stack limit in your program is a few mega bytes, so now there is a potential stack-overflow error.
bool AskToPlayAgain(int counter)
{
char buf[1000]; //<-- allocate lots of stack memory to cause problems!
cout << "counter start: " << counter << " - memory allocated\n";
cout << "play again? y/n... ";
string response;
getline(cin, response);
if(response == "y")
{
return true;
}
else if(response == "n")
{
cout << "Thank you for playing! :D\n";
return false;
}
cout << "invalid response\n";
bool result = AskToPlayAgain(counter + 1);
cout << "counter: " << counter << " - memory cleanup\n";
return result;
}
int main()
{
do
{
printf("play...\n");
} while(AskToPlayAgain(1));
return 0;
}
For this reason its better to use loops in favor of recursive functions. But then again, recursive functions are sometimes useful, and if memory allocation is under control (like in your example) and there is clear path to break the recursion, then go ahead and use it.
i would suggest that in your AskToPlayAgain() function, you do the checking of response == "y" and response == "n" and then do your else section. Although this won't affect your code much, it is certainly easier to read and understand, and if an issue does come up later on , you will not have to spend much time having to go through your code again.
i.e.
if (response == "y") { }
else if (response == "n"){
// your code
}
else {
// your code to handle the invalid response
}
Plus, as suggested in the comments and in the answer by #Barmak Shemirani, It would be better to just use a loop to accomplish this task of repeated asking until a valid response. It's "cheaper" than having multiple function calls.
When the condition is true or false, how can I make it return back and ask the question again, making the user re-enter the value?
Here is what I want to implement:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
int n;
cout<<"Enter numbers. Press 5 to stop: ";
cin>>n;
bool tr=true;
while(tr)
{
if(n!=5)
cout<<"You entered "<<n; //How to make it return again, since its false? I keep getting infinite loops :( ;
else
tr=false;
}
return 0;
}
You need to prompt the user in the while loop, so that it occurs in each iteration:
int n;
bool tr = true;
while(tr)
{
cout << "Enter numbers. Press 5 to stop: ";
cin >> n;
if(n!=5) {
cout << "You entered " << n;
} else {
tr = false;
}
}
Just put all your code (except 'n' and 'tr' definition) in while loop as follow:
int main()
{
int n;
bool tr=true;
while(tr)
{
cout<<"Enter numbers. Press 5 to stop: ";
cin>>n;
if(n!=5)
cout<<"You entered "<<n;
else
tr=false;
}
return 0;
}
The other answers all work, and there is something to be learned about improving program flow from them, but I believe the trick you're asking for is the continue keyword, which skips the remainder of this iteration of the loop.
bool tr = true;
int n;
while (tr)
{
cout << "Enter numbers...";
cin >> n;
if (n != 5)
continue;
else
tr = false;
}
EDIT Part 1: On the continue keyword.
You want to make your code as readable as possible. In this example, its use is unnecessary (as the other posters have shown); but it is the answer to the question "How do I skip the rest of processing in this iteration of my loop and continue to the next iteration?". Usually, such flow-breaking directives actually make code harder to read; but sometimes the opposite is true. Anything (or, at least, almost anything) that can be accomplished with continue or break, can be accomplished without them, so if you're going to use them, you want to have a definite reason for doing so. Usually, when I use continue, it's because I'm looping through a collection of inputs and I want to skip processing the loop whenever the input isn't in the format I'm expecting. Something like this (pseudo-code)...
foreach (Input i in ReceivedInputs)
{
if (i.isBad())
{
cout << "Bad input";
continue;
}
// Do massive block of calculating here.
}
is easier to read than this...
foreach (Input i in ReceivedInputs)
{
if (i.isBad())
cout << "Bad input";
else
{
// Do massive block of calculating here.
}
}
because the second version makes it harder to track what scope you're in, if you're looking toward the end of the massive block of calculating. In this case, I gain code readability by continue, so I use it. But simple code probably shouldn't use it. The break keyword is similar, though it's a lot easier to come up with examples where break is beneficial.
EDIT Part 2: On multiple iterations
This is just an issue of setting up the loop; there are no magic keywords here. The shortest way I can come up with, is probably something like this:
int n = 0;
int numberToTake = 10;
for ( int numbersTaken = 0; numbersTaken < numberToTake; ++numbersTaken)
{
cout << "Enter numbers...";
int n = 0;
for (cin >> n; n != 5; cin >> n)
cout << "Try again.";
// Do whatever processing on n you want to do here.
}
Though I should point out that, doing it this way, the only value you will ever get from the user will be 5, and if he inputs anything that doesn't fit in an integer, you will get unexpected behavior.
EDIT 3: After reading the comment more thoroughly, I think you're just looking for is the more traditional use of the for loop.
No need for the exra bool variable.
The idiom can be: Infinitely loop until the user enters 5:
for(;;) { // Loops infinitely
cout << "Enter numbers. Press 5 to stop: ";
cin >> n;
if(n == 5)
break; // Exits the loop
cout << "You entered " << n; // Before the if if you want to print 5 as well
}
I need to implement a loop where I have to ask the user, and then check the validity of the input (in this case it is necessary to print that is an invalid number). What is the better way to implement it?
Our programming professor does not let us use break, and for(;;) since, as he says, it is a bad practice. Is that correct?
Example 1:
int i = 0;
while(i == 0) {
cout << "...: ";
cin >> i;
/*... Loop body ...*/
if (i == 0)
cout << "Not a valid number" << endl;
}
Example 2:
int i = 0;
do {
cout << "...: ";
cin >> i;
/*... Loop body ...*/
if (i == 0)
cout << "Not a valid number" << endl;
} while (i == 0) // Better while(true) and use break ?
Example 3:
int i = 0;
for ( ;; ) {
cout << "...: ";
cin >> i;
/*... Loop body ...*/
if (i == 0)
cout << "Not a valid number" << endl;
else
break;
}
In your case the second construct (do..while) is the most intuititve for the reader to look at what the code does, and this is important.
The first one isn't so bad, the last one is poor a "for" construct is usually used where there are a limited number of iterations with the limit set in advance. It doesn't have to be, but intuitively that is how a for loop is used.
(Incidentally if the user entered a string that isn't a number you would have to clear the fail flag on cin, but that is not really the question being asked here).
Don't you need to accept zero as an integer? It's good practice to not rely on input numbers having a special meaning.
If the meaning of the loop is to loop infinitely until the task is done there's nothing wrong with clearly saying while(true). I would probably do something more like this (requires C++11): (or use boost lexical_cast)
#include <iostream>
#include <string>
#include <stdexcept>
int infini_asker(){
while (true) {
std::cout << "...: ";
std::string tmp;
std::cin >> tmp;
int i;
try{
i=std::stoi(tmp);
}catch(std::invalid_argument){
continue;
}catch(std::out_of_range){
continue;
}
return i;
}
}
int main(){
int num=infini_asker();
std::cout << " got:" <<num << std::endl;
}
A modification of Example 1 looks to be the best form:
while(true) {
cout << "...: ";
cin >> i;
/*... other stuff ...*/
// Do your input validation here:
// Note that it's much better to whitelist what is
// acceptable input as opposed to checking all of the
// possible cases of invalid input
if (...) { // where .. is the condition for valid input
break
}
}
do-while loops should be reserved for special cases where you want to get the point across that the nested logic should be executed at least once. Anything you can do with do-while, you can do with while(...)
for(;;) is less familiar syntax for a lot of programmers (I didn't know what it meant a year ago), whereas while(true) is much more obvious.
They all work. Like Shmiddty says a for(;;) is not a good programming habit. I would do it like example 2, but I am not a professional programmer.