Run time error of cin.get() [duplicate] - c++

This question already has answers here:
Using getline(cin, s) after cin [duplicate]
(13 answers)
Closed 5 years ago.
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
void cpp_string();
void cstyle_string();
int main()
{
cpp_string();
cstyle_string();
system("pause");
return 0;
}
void cpp_string()
{
string fName, lName;
char grade;
int age;
cout << "What is your first name?";
getline(cin, fName);
cout << "What is your last name?";
getline(cin, lName);
cout << "What letter grade do you deserve?";
cin >> grade;
cout << "What is your age?";
cin >> age;
cout << "Name: " << fName << ", " << lName << endl;
cout << "Grade: " << grade << endl;
cout << "Age: " << age << endl;
return;
}
void cstyle_string()
{
char fNm[20], lNm[20];
char grade;
int age;
cout << "What is your first name?";
cin.get(fNm, 20).get();
cin.clear();
cout << "What is your last name?";
cin.get(lNm, 20).get();
cout << "What letter grade do you deserve?";
cin >> grade;
cout << "What is your age?";
cin >> age;
cout << "Name: " << fNm << ", " << lNm << endl;
cout << "Grade: " << grade << endl;
cout << "Age: " << age << endl;
return;
}
I'm getting output as
What is your first name?demiurge conon
What is your last name?no
What letter grade do you deserve?a
What is your age?22
Name: demiurge conon, no
Grade: a
Age: 22
What is your first name?What is your last name?What letter grade do you deserve?What is your age?Name: ,
Grade: ╠
Age: -858993460
Press any key to continue . . .
but if I run cstyle_string() in different file then I'm not getting any errors code works perfectly.
I want to know why this is happening?

There are two question.
Redundant \n
the state of cin
The last cin in cpp_string is cin >> age.
It will leave a \n not extracted.
In first of cstyle_string is cin.get(fNm, 20).get();
The delimiting character is not extracted from the input sequence if found, and remains there as the next character to be extracted from the stream
the cin.get(FNm, 20) will parse empty input before \n, and no characters are available in the stream in actually. In this case, the failbit flag will be set and next all cin >> operator will fail.
You can only call cstyle_string and press enter directly, the same thing will happen.

Related

Use of getline to read a string with white spaces in a structure

I want to read strings with white spaces into members of a structure. Tried using getline but both the output statements are clubbed with a single cin for both. As per the similar posts here, tried using cin.ignore, but the input is not read into the member of the structure. Pls help. It's a part of my assignment and I'm a beginner in C++. This is how my code looks like:
#include <string.h>
using namespace std;
struct book {
string title, author;
int no_of_pages, year;
float price;
};
int main() {
int N;
cout << "Enter the no. of books whose details are to be entered:" << endl;
cin >> N;
book b[N];
int x;
for (x = 0; x < N; x++) {
cout << "Enter the title of book #" << x + 1 << ":" << endl;
getline(cin, (b[x].title));
// cin.ignore();
cin.ignore(1000, '\n');
cout << "Enter the author's name:" << endl;
getline(cin, (b[x].author));
cout << "Enter the no. of pages:" << endl;
cin >> b[x].no_of_pages;
cout << "Enter the price of book:" << endl;
cin >> b[x].price;
cout << "Enter the year of publishing" << endl;
cin >> b[x].year;
}
for (x = 0; x < N; x++) {
cout << "\n\n";
cout << "The details of book" << x + 1 << " are:" << endl;
cout << "Title :" << b[x].title << endl;
cout << "Author :" << b[x].author << endl;
cout << "No. of pages :" << b[x].no_of_pages << endl;
cout << "Price :" << b[x].price << endl;
cout << "Publishing year:" << b[x].year << endl;
cout << "---------------------------------------------";
}
return 0;
}
There's no point in using cin.ignore() in between two calls to getline. ignore is used to discard remaining characters after numeric input. So the place to use it is after numeric input and before the next getline. Like this
cout << "Enter the title of book #" << x + 1 << ":" << endl;
getline(cin, (b[x].title));
cout << "Enter the author's name:" << endl;
getline(cin, (b[x].author));
cout << "Enter the no. of pages:" << endl;
cin >> b[x].no_of_pages;
cout << "Enter the price of book:" << endl;
cin >> b[x].price;
cout << "Enter the year of publishing" << endl;
cin >> b[x].year;
cin.ignore(1000, '\n');
That said I would just read everything using getline, then convert the strings to numbers where needed. That's simpler and cleaner, all you need to know is how to convert a string to an integer, which you can easily research for yourself.
There are two places you should put cin.ignore in your code:
cout << "Enter the no. of books whose details are to be entered:" << endl;
cin >> N;
// First cin.ignore here
cin.ignore(1000, '\n');
cout << "Enter the year of publishing" << endl;
cin >> b[x].year;
// Second cin.ignore here
cin.ignore(1000, '\n');
Besides this I see two more problems in your code:
#include <string> not <string.h>
add #include <iostream>
Why cin.ignore is necessary? User is expected to provide new line ('\n') delimited input. When getline is used, it leaves the input stream in such a state that the next attempt to read input from stream will start at next line. This is not true for operator >>. What int x; cin >> x; does here is it reads only the integer not the new line character present right after the integer. Hence, the next attempt to read will continue within the same line. getline will then find no character before new line and hence will fetch an empty string. To avoid this and to effectively start reading from the next line, cin.ignore is necessary.

How to create a function to read/write data to struct members?

I'm trying to create a program that read and print students' data with c++. for that, I've created a struct Student, a function to read data from the user and assign it to a struct instance s1 and a function to print students' data on the screen, and I think the problem is with the function that read/write data.
Here is the my code:
#include<iostream>
#include<string>
using namespace std;
struct Student
{
char name[30];
int age;
double gpa;
string department;
};
Student read_data(Student x)
{
cout << "Name (30 characters maximum): ";
cin.get(x.name, 30);
cout << "Age: ";
cin >> x.age;
cout << "Department: ";
cin >> x.department;
cout << "GPA: ";
cin >> x.gpa;
return x;
}
void print_data(Student x)
{
cout <<
"\n***************************************************************" << endl;
cout << "Name: " << x.name << endl;
cout << "Age: " << x.age << endl;
cout << "Department: " << x.department << endl;
cout << "GPA: " << x.gpa << endl;
}
int main()
{
Student s1, s2, s3;
cout << "This program stores -Temporarily- data of three students\n" << endl;
cout << "Enter 1st student's data" << endl;
read_data(s1);
print_data(read_data(s1));
system("pause");
return 0;
}
The output of this code is:
This program stores data of three students
Enter 1st student's data
Name (30 characters maximum): Ahmed Maysara
Age: 22
Department: CS
GPA: 3.5
Name (30 characters maximum): Age: Department: GPA:
***************************************************************
Name:
Age: -858993460
Department:
GPA: -9.25596e+61
Press any key to continue . . .
As you see, the output is out of my expectations :) ..
Any help ?!
Both CinCout and David are correct.
There are a couple of problems with your code as it now stands.
The first problem is that while you successfully call the function read_data(s1), s1 is a just a copy. So, when the function sets all of the values for the student using cin, it is really just setting a copy's values. You can either make it so that you are passing in the original, or you can return the student (which you are doing) and set s1 equal to the result (which you are not).
To make sure that you pass in the original, you can go to where you declared read_data. Instead of saying Student read_data(Student x), you should place an ampersand after the parameter that you don't want to copy Student read_data(Student &x). This is called passing by reference (you reference the original instead of referencing by copy)
Alternatively, you could con just set s1 to the result where you call it in main. You could say s1 = read_data(s1); and that would work fine, though a bit more inefficiently.
Lastly, the other glaring error in the code is that you accidentally call read_data again when you say print_data(read_data(s1)). Instead, say print_data(s1).
Instead of passing and returning the structure object each time on call of read_data and print_data we could add those inside the structure itself, We could create object of Student and call the functions read and print within the same.
struct Student
{
char name[30];
int age;
double gpa;
string department;
Student(): age(0), gpa(0)
{
memset( name, 0, 30 );
}
void read()
{
cout << "\nName (30 characters maximum): ";
cin.get(name, 30);
cout << "\nAge: ";
cin >> age;
cout << "\nDepartment: ";
cin >> department;
cout << "\nGPA: ";
cin >> gpa;
}
void print()
{
cout << "\n***************************************************************" << endl;
cout << "Name: " << name << endl;
cout << "Age: " << age << endl;
cout << "Department: " << department << endl;
cout << "GPA: " << gpa << endl;
}
};
int main()
{
Student s1;
s1.read();
s1.print();
return 0;
}
You are passing copy of s1 into the read_data function, but not bothering to update the value based on the return arg. i.e. something like this should work.
s1 = read_data(s1);
print_data(s1);
Alternatively, pass by reference instead of value:
void read_data(Student& x)
{
cout << "Name (29 characters maximum): "; // requires null terminator
cin >> x.name; // just read into the buffer directly
cout << "Age: ";
cin >> x.age;
cout << "Department: ";
cin >> x.department;
cout << "GPA: ";
cin >> x.gpa;
}
And then later:
read_data(s1);
print_data(s1);
change you read_data with something like this
void read_data(Student& x)
{
cout << "Name (30 characters maximum): ";
///cin.get(x.name, 30);
cin.getline(x.name, 30);
cout << "Age: ";
cin >> x.age;
cin.ignore();
cout << "Department: ";
std::getline(cin, x.department);
///cin >> x.department;
cout << "GPA: ";
cin >> x.gpa;
cin.ignore();
// return x; can't return a value from a void function
}
and in main function or where you are calling the read_data function use
Student s1, s2, s3;
cout << "This program stores -Temporarily- data of three students\n" << endl;
cout << "Enter 1st student's data" << endl;
read_data(s1);
read_data(s2);
read_data(s3);
the reason you are getting weird values in return is that you capture buffer with cin >> instead getline
see
description of getline function
description of cin.ignore function

How do I get the program to request for input for the string "course" before they print out the while/if statement

How do i do that without switching the sequence of asking the questions in my program? I would like to get their age, before asking about the course. However, once the age is keyed in, the program automatically proceeds to print the while/if statement.
#include<iostream>
#include<string>
using namespace std;
int main()
{
int age; //Declares the variable "age"
string name;
string course;
cout << "Hi\n"; //Prints out "Hello World"
cout << "What is your name? ";
getline(cin, name);
cout << "\nHow old are you ? "; //Ask the user their age
cin >> age; //Records the value entered by user
cout << "What course are you picking up in university ? ";
getline(cin, course);
//If number entered is smaller than 0, print the following message
while (age < 0 ) {
cout << "\nYou can't be younger than 0 years old.";
cout << "\nPlease try again";
cout << "\n\nHow old are you ? ";
cin >> age;
}
//If number entered is larger than 100, print the following message
if (age > 100) {
cout << "\nYou are such a blessed person !\n\n";
}
//If number entered is between 1 and 99, print the following message
if (age > 1 && age < 99) {
cout << "Your name is " << name << " ,and you are " << age << " years old.";
cout << "\n You are planning on taking " << course << " in university.";
}
return 0;
}
If getline() is used after cin >>, the getline() sees this newline character as leading whitespace, and it just stops reading any further.
Solution:
Call cin.ignore() before calling getline()
Or
Make a dummy call getline() to consume the trailing newline character from the cin>>
#include<iostream>
#include<string>
using namespace std;
int main()
{
int age; //Declares the variable "age"
string name;
string course;
cout << "Hi\n"; //Prints out "Hello World"
cout << "What is your name? ";
getline(cin, name);
while(true) {
cout << "\nHow old are you ? "; //Ask the user their age
cin >> age; //Records the value entered by user
if(age>=0)
break;
cout << "\nYou can't be younger than 0 years old.\nPlease try again.";
}
cout << "What course are you picking up in university ? ";
getline(cin, course);
//If number entered is larger than 100, print the following message
if (age > 100) {
cout << "\nYou are such a blessed person !\n\n";
}
//If number entered is between 1 and 99, print the following message
if (age > 1 && age < 99) {
cout << "Your name is " << name << " ,and you are " << age << " years old.";
cout << "\n You are planning on taking " << course << " in university.";
}
return 0;
}

Code not allowing user input in strings after first string

I have looked around and can't seem to find an answer to this. I am new to C++ and am attempting to write a program for a class that asks the user for the first and last names of 4 students and their ages. The program will then display the input names and ages and also display the average of the ages.
The issue I am having is that the program allows for input of the first name and age but then skips over the remaining three name input fields and only allows for the remaining three ages to be input.
I apologize if this ends up being a dumb question but I really am at a loss. Any help will be greatly appreciated.
Here is the code I have thus far:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string studentname1;
cout << "Please enter the first student's full name:" << endl;
getline(cin, studentname1);
int age1;
cout << "Please enter the first student's age:" << endl;
cin >> age1;
string studentname2;
cout << "Please enter the second student's full name:" << endl;
getline(cin, studentname2);
int age2;
cout << "Please enter the second student's age:" << endl;
cin >> age2;
string studentname3;
cout << "Please enter the third student's full name:" << endl;
getline(cin, studentname2);
int age3;
cout << "Please enter the third student's age:" << endl;
cin >> age3;
string studentname4;
cout << "Please enter the fourth student's full name:" << endl;
getline(cin, studentname2);
int age4;
cout << "Please enter the fourth student's age:" << endl;
cin >> age4;
cout << "Hello from our group." << endl;
cout << "NAME AGE" << endl;
cout << studentname1 << " " << age1 << endl;
cout << studentname2 << " " << age2 << endl;
cout << studentname3 << " " << age3 << endl;
cout << studentname4 << " " << age4 << endl;
cout << "The average of all our ages is: " << (age1 + age2 + age3 + age4) / 4.00 << endl;
return 0;
}
Since the age variables are int, the cin >> age1; will leave the newline character in the input stream. When next you call getline(), you will get the remainder of that line - which is empty, and so on.
Also, you have a copy-paste bug in your code. getline(cint, studentname2); is run for students 2, 3 and 4.
You can either solve the problem by using getline() for all input:
string agestring;
getline(cin, agestring)
stringstream(agestring) >> age1;
or clear cin when you're done reading the age:
cin >> age1;
cin.ignore();

"getline" prompt gets skipped, not working as intended

Here are my codes:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int age1;
int age2;
string name1;
string name2;
cout << "Please enter the name for one people: " << "\n";
getline (cin, name1);
cout << "Please enter the age for this people: " << "\n";
cin >> age1;
cout << "Please enter the name for another people: " << "\n";
getline (cin, name2);
cout << "Please enter the age for this people too: " << "\n";
cin >> age2;
if ( (age1 <= 100 || age2 <= 100) && (age1 < age2) )
{
cout << name1 << " is younger!" << "\n";
}
else if ( (age1 <= 100 || age2 <= 100) && (age1 > age2) )
{
cout << name2 << " is younder!" << "\n";
}
else if ( (age1 <= 100 || age2 <= 100) && (age1 = age2) )
{
cout << name1 << " and " << name2 << " are of the same age!" << "\n";
}
else
{
cout << "You've got some really old people that are well older than 100!";
}
}
The first getline and cin works fine. I am able to be prompted to input.
However, the second getline and cin are prompted at once, thus I can only input for cin. (The second getline is skipped!)
If I use four cins, the program will work properly.
cin >> age1; does not read the newline character following the number. The newline remains in the input buffer, then prematurely stops the second getline.
So, your program already works as long as you enter the first age and the second name on the same line.
One solution would be to skip whitespace after the numbers:
cin >> age1 >> ws;
Live demo.
first: cin>>age; It takes the number and stores into age but at the same
time it leaves the newline character in the buffer itself. so when there is prompt for next name cin finds that left over newline character in the buffer and takes it as the input. that it why it escapes the name2 prompt.
cout << "Please enter the name for one people: " << "\n";
cin>>name1;
cout << "Please enter the age for this people: " << "\n";
cin >> age1;<<--**this left the new line character in input buffer**
cin.get();<<-- **get that newline charachter out of there first**
cout << "Please enter the name for another people: " << "\n";
getline (cin, name2);
cout << "Please enter the age for this people too: " << "\n";
cin >> age2;
now i give name1-> shishir age1->28
name2->ccr age-> 22 it prints ccr is younder!<-- the spelling is wrong too :D
for more info on getline and get() read c++ primer plus listing 4.3, 4.4, 4.5
Happy coding
You need a ; after getline (cin, name);
hope this helps
I would suggest using cin.ignore(100,'\n'). It ignores the amount of characters you specify when you call it(100 in the example above), up to the char you specify as a breakpoint. For example:
cout << "Please enter the name for one people: " << "\n";
getline (cin, name1);
cout << "Please enter the age for this people: " << "\n";
cin >> age1;
cin.ignore(100, '\n');
cout << "Please enter the name for another people: " << "\n";
getline (cin, name2);
cout << "Please enter the age for this people too: " << "\n";
cin >> age2;
cin.ignore(100, '\n');