Why does this small change halt my C++ program? - c++

I'm new to C++ trying to wrap my head around the fundamentals. This small alteration gives a subtle change in my program behaviour, preventing it's complete run. The problem is every time I arrive at the prompt to enter school, I can't input any text.
Software Info:
OS: Ubuntu 14.04 LTS
G++ version: 4.8.4
This is the code which runs fine:
#include <iostream>
using namespace std;
int main (int argc, char* argv[])
{
string fName, DOB, school;
int age;
cout << endl;
cout << "What is your name: ";
getline (cin, fName);
cout << "What school do you attend: ";
getline (cin, school);
cout << "How old are you: ";
cin >> age;
cout << school << endl;
return 0;
}
This is the code which halts:
#include <iostream>
using namespace std;
int main (int argc, char* argv[])
{
string fName, DOB, school;
int age;
cout << endl;
cout << "What is your name: ";
getline (cin, fName);
cout << "How old are you: ";
cin >> age;
cout << "What school do you attend: "; // this is the only change.
getline (cin, school);
cout << school << endl;
return 0;
}
The only change is moving:
cout << "What school do you attend: ";
getline (cin, school);
from lines 13 & 14 to lines 15 & 16.
Can anyone tell me why this is happening?

Like others have said, there could be a character remaining in the input buffer, most likely the \n charachter when you pressed Enter.
You could add:
while((c = getchar()) != '\n' && c != EOF);
Right after your cin to get all the remaining characters in the buffer, but this is mostly for C.
In C++ you could instead:
std::cin.ignore(256,'\n');
Which will get and discard the next 256 characters it finds in the buffer or until it finds a char equal to the one passed as the second argument, in this case a \n or newline character. Note that for the second parameter, when it is found it is also discarded.

The 'Enter' after age is consumed as a character for school variable in the second program. The easiest solution is to read a dummy character( a useless variable) after reading 'age' in the second program.

Related

C++ istream (cin) and problem with waiting for a ENTER key press

Please, is there a way I can wait for a single ENTER key press in all of the below cases? It works fine except when the std::getline() is used, which consumes the \n, and the ENTER needs to be pressed twice.
The code below works fine:
#include <iostream>
#include <limits>
using std::cout;
using std::cin;
using std::string;
void waitForENTERKeyPress();
int main ()
{
char c;
string s;
cout << "Enter c:"; cin >> c;
waitForENTERKeyPress();
cout << "Enter c:"; c = cin.get();
waitForENTERKeyPress();
cout << "Enter s:"; cin >> s;
waitForENTERKeyPress();
cout << "Enter s:"; std::getline(cin, s);
waitForENTERKeyPress();
return 0;
}
void waitForENTERKeyPress()
{
// Does not work with std::getline(...)
cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n');
cout << "Press an ENTER to continue...\n";
cin.get();
}
====[UPDATE]============================================
Let me rephrase what I am looking for: The way how to make the waitForENTERKeyPress() function working in both cases – with \n in the buffer, when cin operator >> or cin.get() is used and also in cases the std::getline() is used.
From what I understand it is not possible as there is not a way how to detect if the \n is still in the buffer or not.
I have tried to use cin.rdbuf()->in_avail(), but it always returns 0.

Program skipping first input after loop

I'm working on this code which is asking user to input data (student data).
I made a constructor which is taking input of all fields on first run which goes fine on the first run.
When I continue to go again via loop its skipping the Name input every time.
Code
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
class person{
private:
string sName;
string fName;
string sAddress;
public:
person(){
cout << "Enter Details\n";
cout << "Name :";
getline(cin,sName);
cout << "Father's Name :";
getline(cin,fName);
cout << "Address :";
getline(cin,sAddress);
cout << sName << fName << sAddress;
ofstream myfiles("person.txt",ios::app);
myfiles<<sName<<endl;
myfiles<<fName<<endl;
myfiles<<sAddress<<endl;
myfiles.close();
checkLoop();
}
void checkLoop(){
int choice{};
cout << "\nDo you want to continue?\n1)Continue\tx)Anything else for exit!"<<endl;
cin >> choice;
switch(choice){
case 1:
person();
//break;
default:
break;
}
}
};
int main()
{
person p1;
return 0;
}
Output:
Do you want to continue?
1)Continue x)Anything else for exit!
1
Enter Details
Name :Father's Name :
When I choose the first option Continue, it's skipping the "Name" part.
This is happening due to the fact that when you are reading choice using cin, then it will read the choice leaving the newline character behind.
That’s why when you try to read name by getline() it reads endofline character (Due to this in the person.txt you will see there will be blank spaces in name part).
So just use cin.ignore() after cin>>choice;

Getline command gets skipped when an integer cin statement is above [duplicate]

This question already has answers here:
Why does std::getline() skip input after a formatted extraction?
(5 answers)
Closed 2 years ago.
So I made this to try understanding classes and this error keeps coming up where in the command prompt tab, it doesn't ask the user to input the next required input when an integer is being asked. I added a comment in the code below for you to know where the error arises from.
#include <iostream>
using namespace std;
class Anime
{
public:
string Name;
int Year;
string Genre;
Anime(string aName, int aYear, string aGenre)
{
Name = aName;
Year = aYear;
Genre = aGenre;
}
};
int main()
{
string aniName;
int aniYear;
string aniGenre;
// This asks for the year
cout << "Anime Year: ";
cin >> aniYear;
// The "Anime Name" line runs but the input for aniName is not asked and skips to the next input
cout << "Anime Name: ";
getline(cin, aniName);
cout << "Anime Genre: ";
getline(cin, aniGenre);
Anime Anime1(aniName, aniYear, aniGenre);
cout << Anime1.Name << endl;
cout << Anime1.Year << endl;
cout << Anime1.Genre << endl;
}
When i make the integer the last input, it works perfectly, but at if I don't want it to be the last one. In that case, what do I do? Any answer is greatly appreciated.
Try to add #include <string>
And add below code upper the input code.
cin >> aniYear;
// The "Anime Name" line runs but the input for aniName is not asked and
skips to the next input
cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
cout << "Anime Name: ";
getline(cin, aniName);

Weird output at the end of string in Ubuntu terminal

I was trying C++ in Ubuntu terminal. I am getting weird symbols at the end of strings.(This also happened in the past in Codeblocks for Ubuntu but everything worked fine in Codeblocks Windows).
Here is the code:
#include <iostream>
using namespace std;
int main()
{
char name[20];
cout << "\nEnter name: ";
cin.getline(name, 20);
cout << "\nHello ";
cout.write(name, 20);
return 0;
}
Output:
Enter name: Yash
Hello Yash�#��Fy
I have checked other threads with the same problem. All of them had assignment problems where the users did not add '\0' at the end. But here I am doing no such thing. Then why do I get these characters at the end?
cout.write(name, 20);
will (try to) write exactly 20 characters, it will not check for '\0'. You can check such things in your favorite reference.
If you really want to use a char[] for this, you should just write
cout << name;
That will check for the terminating character.
However, it would be better to just ditch the C-style strings and move to std::string instead:
int main () {
std::string name;
std::cout << "\nEnter name: ";
std::getline(std::cin, name);
std::cout << "\nHello ";
std::cout << name;
}
To understand this better, you're never initializing the char name to 0, and cout.write() does not check for null. One option is to initialize char name to 0s from the start:
#include <iostream>
using namespace std;
int main()
{
char name[20] = {0};
cout << "\nEnter name: ";
cin.getline(name, 20);
cout << "\nHello ";
cout.write(name, 20);
return 0;
}
#BaummitAugen's answer is the proper way to do this, though.

While loop fail, when reading int and string C++

I'm trying to read multiple Strings and ints from the user. I want to take pairs of Name and Age and keep doing it until the user types in "done". But my do-while crashes early on, and i can't figure out why?
int number;
string name;
do
{
cout << "Your name: " ;
getline(cin, name);
cout <<name<< " age: " ;
cin >> number;
}
while (name!="done");
Edit: Also after entering "done", i have to enter "done" also on age, why is that?
I tried to run your program in VS 2010, and even when I entered a valid number, the program would, to my surprise skip reading the next name.
It seems to me that cin >> number doesn't swallow the '\n' I naturally entered after the number.
I attempted adding a call to getchar() after each cin >> number and the program suprisingly started working as expected.
So the conclusion is, that you should clean()/ignore() after cin >> number even after the number entered was OK, or resort to using getline() (and then parsing) for reading numbers.
If you want not to input "done"'s age then you have to break out of the loop immediately after it's entered. My final code:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int number;
string name;
while(true)
{
cout << "Your name: " ;
getline(cin, name);
if(name == "done")
break;
cout <<name<< " age: " ;
cin >> number;
cin.clear();
cin.ignore(std::numeric_limits<streamsize>::max(),'\n');
}
}
If someone enters an invalid age, i.e. something that isn't a number, you need to clear the flags of your cin, and also flush any remaining characters.
if( !(cin >> number )
{
cin.clear();
}
cin.ignore( std::numeric_limits<streamsize>::max() );
If it does read a number then you also need to ignore the newline after it.
Use the std namespace
This way
int number;
string name;
do
{
std::cout<<"Your name: " ;
std::cin>>name;
std::cout<<name<<" age: " ;
std::cin>>number;
}
while (name!="done");
Or this
using namspace std;
int number;
string name;
do
{
std::cout<<"Your name: " ;
std::cin>>name;
std::cout<<name<<" age: " ;
std::cin>>number;
}
while (name!="done");
#include <iostream>
#include <string>
int main ()
{
std::string name;
int age;
while (true)
{
std::cout << "Please enter your name: ";
std::cin >> name;
if ( "done" == name )
break;
std::cout << name << ", please enter your age: ";
std::cin >> age;
std::cout << name << ", you are " << age << " years old\n";
}
std::cout << "Bye.\n";
return 0;
}
Mixing use of getline() and >> can be problematic. Best to just avoid it if you can. You could also use getline() for both, and convert the int using a stringstream, or possibly atoi(), but I don't like that much.
Because you give it a string while it expect an int as age.
At the end of the first iterate, as you typed the Enter key to input the age, an extra newline was taken into the cin. So in the second iterate, the newline showed up as an empty line, causing the name to be set as an empty string. Then the program wanted an int as age. If you are not careful enough, you would input a string and cause the program crash.
One suggestion:
To replace:
getline(cin, name);
with:
do {
getline(cin, name);
} while (name.empty());