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();
}
Related
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;
}
I just got into c++ and I'm just experimenting. I want to make a simple program which takes users input and calls one of 2 functions, then the function will print a line and ask the user if they want to go again. The issue is c++, for some reason, does not allow me to call main by simple saying main();
Is there any way to call the main function from another function? I am looking for the simplest solution there is, but I can't find anything :/
Here's the code:
#include <iostream>
#include <string>
using namespace std;
int do_math() {
cout << "Math" << endl;
string user;
cout << "would you like to go again? (y or n): " << endl;
cin >> user;
if (user == "y") {
main();
}
else if (user == "n") {
cout << "Okay, bye!";
exit(0);
}
return 0;
}
int do_eng(){
cout << "Eng";
string user;
cout << "would you like to go again? (y or n): " << endl;
cin >> user;
if (user == "y") {
main();
}
else if (user == "n") {
cout << "Okay, bye!";
exit(0);
}
return 0;
}
int main() {
string user;
cout << "Would you like to do math or end?:";
cin >> user;
if (user == "math") {
do_math();
}
else if (user == "end") {
do_eng();
}
return 0;
}
The issue is c++, for some reason, does not allow me to call main by
simple saying main(); Is there any way to call the main function from
another function? I am looking for the simplest solution there is, but
I can't find anything :/
No, you don't want to call main from any of your code.
Not that you should want to do this ... but the simplest solution is to provide a callable function, and get into it in the simplest way from main.
Perhaps:
int myMain()
{
string user;
cout << "Would you like to do math or end?:";
cin >> user;
if (user == "math") {
do_math();
}
else if (user == "end") {
do_eng();
}
return 0;
}
int main(int, const char**)
{
return myMain();
}
Lesson 1 - try to add another level of indirection (i.e. myMain()) does not have the restrictions of main()
Lesson 2 - learn something about recursion ... it seems you probably want to avoid it, here. (i.e. if you always invoke myMain(), how does your program ever terminate?
Lesson 3 - On my system, if the program terminates, I can up-arrow and launch it trivially. Terminal shells do this stuff for you. Perhaps this would be a better approach ... to always terminate unless the user selects one of the action choices (math, burp, etc.)
Lesson 4 - research other programs and how their user interface works. Find a model you like.
Note - I suppose, for your code to call myMain() again, you will need to 'forward declare' the function.
No, the standard specifically disallows calling main() from program code. What you want is to have a loop in main :
int main()
{
bool bContinue;
do
{
/* do something */
std::cout << "Do you want to go again?";
cin >> bContinue;
} while(bContinue);
}
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;
#include <iostream>
#include <time.h>
#include <stdlib.h>
using namespace std;
int main()
{
int password;
system("cls");
cout <<"Login"<< endl;
cout <<"Enter password to continue"<< endl;
cin >> password;
cin.ignore().get();
if( password == 1111)
{
system("cls");
cout <<"Access Granted"<< endl;
system("PAUSE");
system("cls");
return main();
}
//Want to make if( password == 1111) return to main(), but start where it left off
//I want it to start at cout <<"Files:'<< endl;
cout <<"Files:"<< endl;
cout <<"\n E \n N \n G \n S \n"<< endl;
cout <<"Choose a file"<< endl;
string file;
cin >> file;
cin.ignore().get();
if(file == "E" || file == "e")
{
system("cls");
cout <<"E:"<< endl;
cout <<"Age:"<< endl;
cout <<"Grade:"<< endl;
cout <<"Eye color:"<< endl;
cout <<"Hair color:"<< endl;
system("Pause");
}
else if(file == "N" || file == "n")
{
system("cls");
cout <<"N:"<< endl;
cout <<"Age:"<< endl;
cout <<"Grade:"<< endl;
cout <<"Eye color:"<< endl;
cout <<"Hair color:"<< endl;
system("Pause");
}
else if(file == "G" || file == "g")
{
system("cls");
cout <<"G:"<< endl;
cout <<"Age:"<< endl;
cout <<"Eye color:"<< endl;
cout <<"Hair color:"<< endl;
system("Pause");
}
else if(file == "S" || file == "s")
{
system("cls");
cout <<"S:"<< endl;
cout <<"Age:"<< endl;
cout <<"Eye color:"<< endl;
cout <<"Hair color:"<< endl;
system("Pause");
}
else
{
system("cls");
cout<<"Access Denied!"<< endl;
system("PAUSE");
return 0;
}
return 0;
}
Having trouble figuring out how to continue where the main function left of. I have been teaching myself how to code so I don't know if that's even possible. Read the comment I left In the code to better understand what I am speaking of. Thx
If you remove this line:
return main();
then the computer will continue executing the instructions in the order they are written - in particular, the next one will be cout <<"Files:"<< endl;.
To control the flow of your program, you have multiple options.
If you're doing things multiple times, you have for and while loops. If you want to stop a loop and get out, use break. If you want to skip to the next iteration, use continue.
If you want to simply jump to a different place in the program, you can use goto but it's a code smell. It's generally better to avoid it as it tends to compromise readability.
If you want to do a task that can he interrupted, you can use a void function. If you want the function to stop what it's doing and continue main, use return.
However, in your particular example, it seems like you don't quite understand how an if statement works.
If the ifs condition is true, it executes whatever is in the curly braces ({ ... }). It continues execution right after the closing brace automatically. You don't need to return to main explicitly.
What you actually did there (by mistake) is write a recursive function (one that calls itself until a condition is met).
You seem to have significantly misunderstood program flow in a C++ program. return main() will make a fresh call into main, so the user will see the "login" prompt again. When that call to main has ended, because you used the keyword return, it will exit the previous call to main. Neither of these is what you want. It's also explicitly forbidden by the C++ standard to call main from another function.
I also note that after the long block of indented functionality, you have an else statement that looks like it is the else to if (password == 1111).
Indentation means nothing to the C++ compiler, it's purely for human readability.
I think what you are trying to achieve is something more like this:
if (password == 1111)
{
std::cout << "Access granted\n";
}
else
{
std::cout << "Access denied\n";
return 0;
}
std::cout << "Files:\n";
Here, if the user types 1111, then the first compound block of code is executed, and execution resumes after the end of the if/else block, i.e. the next instruction is to print Files.
If the user types something else, the else block is executed. It finishes with return 0 which exits the function and returns the value of 0 to the caller.
#include <iostream>
#include <string>
int main()
{
std::cout << "Login:\n";
std::string password;
std::getline(std::cin, password);
if (password == "1111")
std::cout << "That's correct.\n";
else {
std::cout << "Access denied.\n";
return 0;
}
std::cout << "Files:\n";
// your code here
}
Demo: http://ideone.com/DSYAG4
I'm making a small program that uses a if else statement, but instead of using numbers to control the flow i want to be able to make the control work with with yes and no;
for example:
cout << "would you like to continue?" << endl;
cout << "\nYES or NO" << endl;
int input =0;
cin >> input;
string Yes = "YES";
string No = "NO";
if (input == no)
{
cout << "testone" << endl;
}
if (input == yes)
{
cout << "test two" << endl;
//the rest of the program goes here i guess?
}
else
{
cout << "you entered the wrong thing, start again" << endl;
//maybe some type of loop structure to go back
}
but I can't seem to get any variations of this to work, i could make the user type a 0 or 1 instead but that seems really stupid, i'd rather it be as natural as possible, users don't speak numbers do they?
also i need to be able to simply add more words, for example "no NO No noo no n" all would have to mean no
hopefully that makes some sense
also i would love to make this using a window but i've only learned basic c++ so far not even that and i cant find any good resources online about basic windows programming.
You're not reading in a string, you're reading in an int.
Try this:
string input;
instead of
int input = 0;
Also, C++ is case-sensitive, so you can't define a variable called Yes and then try to use it as yes. They need to be in the same case.
btw, your second if statement should be an else if, otherwise if you type in "NO" then it will still go into that last else block.
First of all, input must be std::string, not int.
Also, you've written yes and no wrong:
v
if (input == No)
// ..
// v
else if (input == Yes)
^^^^
If you want your program to work with "no no no ..", you could use std::string::find:
if( std::string::npos != input.find( "no" ) )
// ..
The same with "Yes".
Also, you could do this to be almost case-insensitive - transform the input to upper-case letters (or lower, whatever ), and then use find.This way, yEs will be still a valid answer.
bool yesno(char const* prompt, bool default_yes=true) {
using namespace std;
if (prompt && cin.tie()) {
*cin.tie() << prompt << (default_yes ? " [Yn] " : " [yN] ");
}
string line;
if (!getline(cin, line)) {
throw std::runtime_error("yesno: unexpected input error");
}
else if (line.size() == 0) {
return default_yes;
}
else {
return line[0] == 'Y' || line[0] == 'y';
}
}
string input;
cin >> input;
if (input == "yes"){
}
else if (input == "no"{
}
else {
//blah
}