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

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;

Related

I am trying to end my C++ program when the user presses 'Ctrl-D'

my program has read in a large file of words (a dictionary) and inserted them all into a hash table. I am prompting the user to lookup a word and I want them to be able to terminate the program by pressing Ctrl-D. This is what I have tried but when I press Ctrl-D it just gets stuck in a loop printing out what I have in the else statement. I am using Unix. I have attempted looking this up on this website and nothing was working that I was trying hence why I am asking my own question. Any thoughts? PS. The transform is to make the user input all uppercase to match the file I am reading from.
void query(){
bool done = false;
string lookupWord;
while(!done){
cout << "Type a word to lookup or type ctrl-D to quit: ";
cin >> lookupWord;
if(atoi(lookupWord.c_str()) == EOF)
done = true;
else{
transform(lookupWord.begin(), lookupWord.end(), lookupWord.begin(), ::toupper);
cout << endl << "Word: " << lookupWord << endl;
cout << endl << "Definition: " << myDict.lookup(lookupWord) << endl << endl;
}
}
}
atoi(lookupWord.c_str()) == EOF
This doesn't do what you think it does. This checks the return value of atoi() and compares it to EOF. EOF is typically defined as -1. So, the code ends up setting done only when -1 is typed in. Which is not what you want.
std::istream has a convenient operator bool that tests whether the file stream is in a good state. So, all that really needs to be done is:
if (cin >> lookupWord)
{
// Your existing code is here
}
else
{
done=true;
}

cin.get(); doesn't work when I put it in a if statement

I used cin.get() to get the program to pause and wait for user input, and it works fine. The moment I put it in an if statement, it just skips that "wait" period and continues on with the code? How can I solve this. Here is the section that is not working.
do
{
cout << "\n\n\nEnter the number of one of the following and I will explain!\n";
cout << "1.integer 2.boolian 3.floats 4.doubles 5.character";
cout << "\n\n[when you are done type 'done' to continue]\n\n";
cin >> option;
if (option = 1);
{
cout << "\nInteger is the variable abbreviated as 'int' this allows C++ to only";
cout << "\nreadwhole and real numbers \n\n";
cin.get(); //this is the part where it just skips.. it should wait
}
} while (var = 1);
The problem is that cin >> option will extract whatever integer is in the input stream but will leave the following newline character (which is there from hitting enter after typing in the value). When you do cin.get() it is simply extracting that newline character which is already there. Like so many other questions like this, the solution is to empty the input stream after you've extracted into option:
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
You are also using assignment (=) where you should be comparing for equality (==).

cin condition checking error

I am a beginner programmer learning c++. I am having a nagging issue with the cin command.
In the program section below, if I enter a wrong type at the 1st cin command, the program will not execute any of the following cin commands at all, but will execute the rest of the program.
//start
#include <iostream>
using namespace std;
int main()
{
int x=0;
cout << endl << "Enter an integer" << endl;
//enter integer here. If wrong type is entered, goes to else
if (cin >> x){
cout << "The value is " << x << endl;
}
else {
cout << "You made a mistake" << endl; //executes
cin.ignore();
cin.clear();
}
cout << "Check 1" << endl; //executes
cin >> x; //skips
cout << "Check 2" << endl; //executes
cin >> x; //skips
return 0;
}
//end
Instead of the if else, if i put the same concept in a loop
while (!(cin >> x))
the program goes into an infinite loop upon enterring a wrong input.
Please help me explain this phenomenon, as the text book i am following says the code typed above should work as intended.
Thank you
cin is an input stream. If an error occurs cin goes into a let's call it "error occured" state. While in this state no character input can be made, your request to collect a character from the input stream will be ignored. With clear() you clear the error and the input stream stops ignoring you.
Here is the ignore function prototype
istream& ignore ( streamsize n = 1, int delim = EOF );
This function gets characters from the input stream and discards them, but you can't get any character if your stream is ignoring you, so you have to first clear() the stream then ignore() it.
Also, a note on the side: If someone inputs, for example "abc", on the first input request your cin gets only one character that is 'a' and "bc" stays in the buffer waiting to be picked up, but the next call to cin gets the 'b' and 'c' stays in the buffer, so you again end up with an error.
The problem with this example is that the cin.ignore() if no arguments are handed to it only ignores 1 character after you clear(). and the second cin gets 'c' so you still have a problem.
A general solution to this problem would be to call
cin.ignore(10000, '\n');
The first number just has to be some huge number that you don't expect someone would enter, I usually put in 10000.
This call makes sure that you pick up all the characters from the false input or that you pick up every character before the enter was pressed so your input stream doesn't get into the "error occurred" state twice.
You may also want to try
if ( std::cin.fail() )
as a backup to prevent a crash due to input of the wrong type when prompted

getline(cin.name) gets skipped

I call a function from a function in C++ that has the line getline(cin,name) where name is a string. the first time through the loop, the program does not wait for input. It will on all other passes through the loop. Any ideas on why?
void getName (string& name)
{
int nameLen;
do{
cout << "Enter the last Name of the resident." << endl << endl
<< "There should not be any spaces and no more than 15"
<< " characters in the name." << endl;
getline(cin,name);
cout << endl;
nameLen = name.length();// set len to number of characters input
cout << "last" << name << endl;
}
while (nameLen < LastNameLength);
return;
}
Make sure there isn't left overs since the last time you read something from cin, like:
In an earlier point in your program:
int number;
cin >> number;
The input you give:
5
Later in the program:
getline(cin,name);
and getline will seem to not be called, but rather it collected the newline from the last time you took input because when you use cin >> it leaves new lines.
It may be because of the input stream. The getline function stops reading input after is receives the first newline char. If for example there are multiple newlines within the buffer of std::cin - the getline will return every time it encounters one.
Check the input you are expecting.
Do you have any:
cin << variableName;
lines of code? I ran into getline() skipping run-time errors when I was using:
cin << intvariable and subsequently getline(cin, variable).
This is because the cin stream object holds a buffer of input. When you enter the newline character I assume it is trunacated from the stream going to the variable asisgnment, yet is still contained within the cin object instance itself.
One workaround I used is cin.ignore(); after the cin << integer statement.
Another user mentioned parsing all input from getline into integers, floats - not root beer -, and strings. Good luck and check your code for the dual use of cin & getline().

Ignore Spaces Using getline in C++ [duplicate]

This question already has answers here:
Need help with getline() [duplicate]
(7 answers)
Closed 7 years ago.
Hey, I'm trying to write a program that will accept new tasks from people, add it to a stack, be able to display the task, be able to save that stack to a text file, and then read the text file. The issue comes when I am trying to accept input from the user, whenever you enter a string with a space in it, the menu to choose what to do just loops. I need a way to fix this. Any help would be greatly appreciated.
// basic file io operations
#include <iostream>
#include <fstream>
#include <stack>
#include <string>
using namespace std;
int main () {
//Declare the stack
stack<string> list;
//Begin the loop for the menu
string inputLine;
cout << "Welcome to the to-do list!" << endl;
//Trying to read the file
ifstream myfile ("to-do.txt");
if(myfile.is_open()){
//read every line of the to-do list and add it to the stack
while(myfile.good()){
getline(myfile,inputLine);
list.push(inputLine);
}
myfile.close();
cout << "File read successfully!" << endl;
} else {
cout << "There was no file to load... creating a blank stack." << endl;
}
int option;
//while we dont want to quit
while(true){
//display the options for the program
cout << endl << "What would you like to do?" << endl;
cout << "1. View the current tasks on the stack." << endl;
cout << "2. Remove the top task in the stack." << endl;
cout << "3. Add a new task to the stack." << endl;
cout << "4. Save the current task to a file." << endl;
cout << "5. Exit." << endl << endl;
//get the input from the user
cin >> option;
//use the option to do the necessary task
if(option < 6 && option > 0){
if(option == 1){
//create a buffer list to display all
stack<string> buff = list;
cout << endl;
//print out the stack
while(!buff.empty()){
cout << buff.top() << endl;
buff.pop();
}
}else if (option == 2){
list.pop();
}else if (option == 3){
//make a string to hold the input
string task;
cout << endl << "Enter the task that you would like to add:" << endl;
getline(cin, task); // THIS IS WHERE THE ISSUE COMES IN
cin.ignore();
//add the string
list.push(task);
cout << endl;
}else if (option == 4){
//write the stack to the file
stack<string> buff = list;
ofstream myfile ("to-do.txt");
if (myfile.is_open()){
while(!buff.empty()){
myfile << buff.top();
buff.pop();
if(!buff.empty()){
myfile << endl;
}
}
}
myfile.close();
}else{
cout << "Thank you! And Goodbye!" << endl;
break;
}
} else {
cout << "Enter a proper number!" << endl;
}
}
}
You have to add cin.ignore() right after options is chosen:
//get the input from the user
cin >> option;
cin.ignore();
And cin.ignore() is not necessary after your getline:
getline(cin, task); // THIS IS WHERE THE ISSUE COMES IN
//cin.ignore();
The problem is in options - if you didn't call cin.ignore() after it, options will contain end of line and loop will continue...
I hope this helps.
Don't do this:
while(myfile.good())
{
getline(myfile,inputLine);
list.push(inputLine);
}
The EOF flag is not set until you try and read past the EOF. The last full line read read up-to (bit not past) the EOF. So if you have have zero input left myfile.good() is true and the loop is enetered. You then try and read a line and it will fail but you still do the push.
The standard way of reading all the lines in a file is:
while(getline(myfile,inputLine))
{
list.push(inputLine);
}
This way the loop is only entered if the file contained data.
Your other problem seems to stem from the fact that you have:
std::getline(std::cin,task); // THIS is OK
std::cin.ignore(); // You are ignoring the next character the user inputs.
// This probably means the next command number.
// This means that the next read of a number will fail
// This means that std::cin will go into a bad state
// This means no more input is actually read.
So just drop the cin.ignore() line and everything will work.
Instead of using ">>" directly on your stream you might consider using getline and then attempting to fetch your option from that. Yes, it's less "efficient" but efficiency isn't generally an issue in such situations.
You see, the problem is that the user could enter something silly here. For example, they could enter something like "two", hit enter, and then your program is going to pitch a fit as it happily continues trying to decipher an empty option over and over and over and over again. The user's only recourse the way you have it set up (and the way those recommending use of ignore() are recommending) is to kill your program. A well behaved program doesn't respond in this way to bad input.
Thus your best option is not to write brittle code that can seriously break down with the most modest of user ignorance/malfunction, but to write code that can handle error conditions gracefully. You can't do that by hoping the user enters a number and then a newline. Invariably, someday, you'll bet poorly.
So, you have two options to read your option. First, read a full line from the user, make sure the stream is still good, and then turn the string you get into a stream and try to read your integer out of it, making sure this other stream is still good. Second option, attempt to read a number, verify that the stream is still good, read a line and make sure the stream is still good and that your string is empty (or just ignore it if it isn't, your choice).
#Vladimir is right. Here is the mechanism behind the bug:
When you enter option '3', what you actually put into stream is "3\n". cin >> option consumes "3" and leaves "\n". getline() consumes "\n" and your call to ignore() after getline() waits for user input.
As you can see, teh sequence of events is already not what you expected.
Now, while ignore() is waiting for input, you type in your line. That line you're typing is what will go to "cin >> option.
If you just give it one symbol, ignore() will dispose of it for you, and option will be read correctly. However, if you give it non-numeric symbols, stream will set failbit when trying to read the option. From that point on, your stream will refuse to do anything. Any << or getline will not set any new values in the variables they are supposed to change. You'll keep 3 in option and "" in task, in a tight loop.
Things to do:
always check cin.eof(), cin.fail() and cin.bad().
always initialize your variables and declare them in the narrowest scope possible (declare option=0 right before it's read).
I just figured out a way to kind of hack through it, not the greatest but it works. Create a character array, and then accept input in the array, and then put everything into the array into the string.
char buff[256];
cout << endl << "Enter the task that you would like to add:" << endl;
cin >> task;
task += " ";
cin.getline(buff, 256);
for(int i = 1; buff[i] != 0; i++){
task += buff[i];
}