Why it repeats 5 times? - c++

void firstSentence(void){
string incorrectSentence;
string correctSentence = "I have bought a new car";
cout << "Your sentence is: I have buy a new car" << endl;
cout << "Try to correct it: ";
cin >> incorrectSentence;
if(incorrectSentence == correctSentence){
cout << "Goosh. Your great. You've done it perfectly.";
}
else{
firstSentence();
}
}
That's my function I am trying to call in my program. But I am stuck little and angry because I can't find solution on my own. What it does is, that if the condition in "if statement" is true, my output is not what I expected. Output is 5 times repeated "Try to correct it. Your sentence is: I have buy a new car ..
Why it repeats exactly 5 times and whatever, what's going on there and why it's not working?

This:
cin >> incorrectSentence;
does not read a line but a whitespace-delimited token. If your input is the correct sentence, that means that the first time it will read "I", while the rest of the sentence remains in the input stream. The program correctly determines that "I" is not the same as "I have bought a new car", loops, and reads "have" the second time around. This is also not the same as the correct sentence, so it loops again and reads "bought". This continues until everything is read from the stream, at which point cin >> incorrectSentence; blocks again .
The solution is to use
getline(cin, incorrectSentence);
...which reads a line.

Related

Understanding why unwanted iterations of a cout statement occur [duplicate]

This question already has answers here:
Why does std::getline() skip input after a formatted extraction?
(5 answers)
Closed 3 years ago.
I am working with some C++ code. I have a while-loop set up to allow me to run through some code x-number of times. The while loop terminates once the user indicates that they do not want to run through the code again.
#include <iostream>
#include <string>
using namespace std;
char request;
int main() {
while (request != 'N')
{
string getCode = "";
while (getCode.length() != 3)
{
cout << "Please enter your container's region code (A or B followed by two-number identification)" << endl;
getline(cin, getCode);
if (getCode.length() != 3)
{
cout << "Error" << endl;
}
}
//clear the screen
system("cls");
//get letter
if (getCode.at(0) == 'A' || getCode.at(0) == 'B')
{
if ((getCode.at(1) >= '0' && getCode.at(1) <= '9') && (getCode.at(2) >= '0' && getCode.at(2) <= '9'))
{
if (getCode.at(0) == 'A')
{
cout << "The shipping charge is $25" << endl;
}
else if (getCode.at(0) == 'B')
{
cout << "The shipping charge is $30" << endl;
}
}
else
{
cout << "Error" << endl;
}
}
else
{
cout << "Error...Please enter the code as A or B followed by two numbers" << endl;
}
//Again?
cout << "Would you like to enter in another shipping identification number?" << endl;
cin >> request;
}
cout << "Thank you" << endl;
//End Program
system("pause");
return 0;
}
When I indicated that yes (entering 'Y' to the 'Would you like to enter in another shipping identification number question') I would like to run through the code again, the program outputs an unwanted 'Please enter your container's region code (A or B followed by two-number identification' and 'error' statement. Also please note, the code is inside 'int main()' and that I have properly formatted my 'include' statements.
Your question is to understand why this is happening, so here's the explanation. The code you wrote states thusly:
string getCode = "";
while (getCode.length() != 3)
{
cout << "Please enter your container's region code...
As you see, getCode is always initialized to an empty string. Immediately afterwards, if its length is not 3, this question is outputted.
You need to understand that your computer will always do exactly what you tell it to do. Your computer will not do what you want it to do, but only what you tell it to do. The above is what you told your computer to do, and your computer will always obediently follow its strict instructions, every time it runs this code. That's pretty much the explanation, and there's nothing more to understand.
This section of code is inside another loop, and you indicated that you do not wish the prompt to appear on second and subsequent iteration of the loop, only on the initial one.
However, there's nothing in your instructions to your computer, above, that specify this. You didn't tell your computer that this is what it should do, so why do you expect your computer to do that, entirely on its own? Every time your computer executes these statements shown above, this is exactly what will happen. Nothing more, nothing less. Whether it's the first time inside the outer while loop, or on each subsequent time the while loop iterates, it doesn't matter. The code always does exactly the same thing: getCode gets created and set to an empty string, and because its length is not 3, the inner while loop runs, prints the prompt and calls std::getline to read a line of text from std::cin. At the end of your while loop, if your instructions to your computer indicate that it should run the code in the while loop again, from the beginning (because that's what the while loop does), then the above instructions get executed.
If you now understand why your computer does this (because that's what you told it to do), then you should easily figure out what to tell your computer so it doesn't do this. If you want your computer to print the prompt only the first time it executes the while loop, then this is exactly what you need to tell your computer: set a flag before the while loop, print the prompt only if the flag is set (with all other existing logic remaining the same), and then clear this flag afterwards, so the next time the while loop runs, your computer will do exactly what you told it to do, and not print the prompt.
when I indicate 'Y' to the prompt 'Would you like to enter in another shipping identification number?', it outputs the following: 'Please enter your container's region code (A or B followed by two-number identification)' 'error' 'Please enter your container's region code (A or B followed by two-number identification' . When I input 'Y' I only want it to output 'Please enter your container's region code (A or B followed by two-number identification)'...I only want it to output once
Now that I understand your question, what's happening is an newline (\n) is getting added to the std::cin buffer at these lines right here:
//Again?
cout << "Would you like to enter in another shipping identification number?" << endl;
cin >> request;
This makes even more sense especially when combined with your other comment:
Before int main() there should be a 'char request;
So request a single char. That means when you type something like this:
Y
The newline is added to std::cin as well. That can't be stored in a single char, and the >> may not remove it either. That means it's just sitting here.
What this does is when you get to your if statement at the beginning of the loop again:
while (request != 'N')
{
string getCode = "";
while (getCode.length() != 3)
{
cout << "Please enter your container's region code (A or B followed by two-number identification)" << endl;
getline(cin, getCode);
if (getCode.length() != 3)
{
cout << "Error" << endl;
}
}
getline() sees the newline you added previously and instantly returns an empty string. Empty strings have a length of 0, so it fails your if statement, which prints the error.
The solution is simple, just tell std::cin to ignore the newline:
//Again?
cout << "Would you like to enter in another shipping identification number?" << endl;
cin >> request;
cin.ignore(1, '\n');

How to prevent if statement from executing when receiving multiple inputs that fulfill the statement

So I recently finished a beginner'c course on C++, and wanted to make my own "chat bot" since apparently it's easy and been done a million times. The problem I'm having, is that when the user input matches more than one possibility in my 'if' statement, it issues the command more than once.
class response{
public:
void answer() {
string x;
cin >> x;
if (x=="Hello"||x=="hello"||x=="Hi"||x=="hi"||x=="hey"||x=="Hey") {
cout << endl << "Hello!" << endl << endl;
}
else {
cout << endl << "I didn't understand that." << endl << endl;
}
} };
For example, if you input: "hey hi", you get: "Hello! Hello!"
Or if you input "hey squid" you get "Hello! I didn't quite understand that."
And so on and so on. I'm wondering if there is any way to make it so that, unless your entire string matches the exact x== values, it will execute the else statement, and only execute it once.
Edit: The solution worked. Thanks for all the help! Some of you were asking about how I was using the class statement in main. I hope this helps clarify how I used it:
int main()
{
cout << "Hello! I am Drew Bot 1.0." << endl << endl;
for(;;){
response test;
test.answer();
}
}
For what you describe to occur (and it would make sense because you're writing a chat bot), response::answer() would have to be called in a loop.
The tokens of std:cin are delimited by the space character, so when you stream it into a variable you are only getting the first word and the rest of the words remain in the std::cin stream. The part that is catching you is that is if std::cin already has a token, it does not wait for user input.
So, if you type "hey hi hello squid" in the first call to response::answer, it will only check the first word. Subsequent calls will check the rest of the words without prompting the user until nothing remains in the input stream.
A solution would be to use getline (std::cin, x); in place of std::cin >> x.
getline will read to the next newline or EOF, but you can also specify your own delimiter: getline(std::cin, x, ' ');

Learning C++ and I don't know what I did wrong here

I'm currently learning C++ and I was asked to write a code using the while function. The code runs, but it gives does not print the line Dear .... What did I do wrong here?
cout << "Hello! Please write your recipient and the letter, then press enter:\n";
string name{ "" };
string current{ "" };
string letter{ "" };
cin >> name;
while (cin >> current){
if (current != name){
letter += " " + current;
}
}
cout << "Dear " << name << "," << letter;
keep_window_open();
return 0;
To output the result you have to make cin >> current false. To do this, use Ctrl-D to send end of file (EOF) to cin which will cause the loop to stop executing.
Edit: Apparently in Windows, the sequence is Ctrl-Z.
Edit: As #pdw noted, cout will need to be flushed. This is usually done when there is a newline character, but since you don't have one you can use std::flush or std::endl:
cout << "Dear " << name << "." << letter << std::flush;
while (cin >> current)
To make this loop interrupt you need to put end of stream marker into std::cin. Type Ctrl-Z on Windows or Ctrl-D on Unix like systems at the end of input to achieve that.
You have an infinite loop here. while (cin >> current) will always evaluate to true, and will just continuously wait for user input. That is why you never reach the last line of code. You are just continuously creating new values for current on each input in the prompt and then adding them to letter. I would recommend not using a while loop, or set some escape input. For example, if the user enters done, exit from the loop, using break;

Usage of two gets() in C++

I am learning about classes in C++. I made a simple program using the concept of classes. In the program I need the person to enter the details of the book. Here is that function:
void Book::add(){
cout << "Enter name of Book: ";
gets(book_name);gets(book_name);
cout << "\n\nPlease enter the book id: ";
cin >> book_id;
cout << "\n\nThank you the book has been added.";
total++;
input = getchar();
getchar();
}
Notice in the third line I have to use two gets to get the user input. If I use one gets
this is the output. It just skips the gets statement. Similarly at other places also I have to use two getchar statements. I was able to find the answer for that on SO itself. Ex Why my prof. is using two getchar. I couldn't find the answer for two gets statements, though. Here is the complete code in case it is required.
That is because you have a trailing new line (from Enter) character remaining on the stream that is not read by the first read operation. So the first gets(book_name) will read that and continue to the next request for input.
use getline to remove any remaining offending input from the stream.
void Book::add(){
string garbage;
getline(cin,garbage); // this will read any remaining input in stream. That is from when you entered 'a' and pressed enter.
cout << "Enter name of Book: ";
gets(book_name);
getline(cin,garbage); // this will read any remaining input in stream.
cout << "\n\nPlease enter the book id: ";
cin >> book_id;
Anyways just use the safer way of reading input from streams
cin >> book_name;
instead of gets. Then you will not have such problems.
if you want to read space separated inputs in to one string the use std::getline (like I did for garbage above)
std::getline(cin,book_name);
cin and cout are from <iostream> and gets comes from <cstdio>. It's not good idea to mix those two if you don't exactly know how those two work and what is the difference.
Better idea is to use cin.getline()
cin.getline(char* s, streamsize n );
The second parameter is the maximum length of the input.

While Loop Repeats 4 Times

I'm trying to only accept integers as input and loop through it at the same time as a sort of validation. The problem is, when a user enters something along the lines of "Two" the while loop goes through the input 3 different times before asking the user again. Is there a way to prevent this from happening and just skip the 3 iterations?
cout << "Enter Student ID: ";
while(!(cin >> id))
{
cout << "\nERROR: Please enter a Positive Whole Number" << endl;
cin.clear();
cin.ignore ();
cout << "Enter Student ID: ";
}
You can use this.
cin.ignore (std::numeric_limits<streamsize>::max (), '\n') ;
It would skip all the lines and you wont get extra loop iterations, no matter how many invalid characters you enter.
The reason for your while loop iterating is that the stream is not being extracted completely so by just using this line
cin.ignore (std::numeric_limits<streamsize>::max (), '\n') ;
the loop will iterate only for once because no matter how much big input you give it will be extracted. Cin.ignore() only removes the one character from the stream.
In your case if you enter "two" then after firs iteration only 't' will be extracted and the input would be "wo" for the second iteration. But by adding this line stream would be empty in the second iteration and will take input from user.