Problems with getline() function? [duplicate] - c++

This question already has answers here:
getline not asking for input? [duplicate]
(3 answers)
Closed 8 years ago.
I have a problem with the getline function in the code below. In the "get" info section I want to be able to store a whole sentence, but I can't make it work.
When I open up my program it just skips the input for the info.
p.s: I'm new to C++
Here is the section of the code where i have the problem (Enter the information):
void add() {
string name;
string faction;
string classe;
string race;
string info;
ofstream wowdatabase("wowdatabase.txt", ios::app);
cout << "Add a race or class" << endl;
cout << "---------------------------------------------------------" << endl;
cout << "" << endl;
cout << "Enter the name of the race or class (only small letters!):" << endl;
cin >> name;
cout << "Enter Race (Type -, if writen in name section):" << endl;
cin >> race;
cout << "Enter Class (Type -, if writen in name section):" << endl;
cin >> classe;
cout << "Enter faction (Alliance/Horde):" << endl;
cin >> faction;
cout << "Enter the information:" << endl;
getline(cin, info);
wowdatabase << name << ' ' << faction << ' ' << classe << ' ' << race << ' ' << info << endl;
wowdatabase.close();
system("CLS");
main();
}
Now it works fine =) but, when i want to output the info again it only shows the first word in the sentence?

Before this statement
getline(cin, info);
make the following call
cin.ignore( numeric_limits<streamsize>::max(), '\n' );
To use this call you must include header <limits>.
The problem is that after executing statement
cin >> faction;
the new line character that corresponds to enetered key ENTER is in the input buffer and the next getline call reads this character.

After you read fraction an empty line character will be left over. The consequent call to getline will read it. To avoid that add a call to cin.ignore before the getline call.

Related

I am making a quiz-like program. I already wrote the string answer ="George Washington". but when the user inputted the answer, it's wrong

answer = "George";
cout << "\t\t\t\t\t Who was the first President of United States?" << endl;
cout << "";
cout << "";
cout << "Congrats " << player1_name << " (Player1). Now, type in your answer:";
cin >> player1_answer;
if (player1_answer == answer){
cout << "check";
}else{
cout << "x";
}
This is my code. But when the user inputted the answer as exactly as what was written in the answer variable, it outputs 'x'. But if the user inputted the same answer excluding the space between "George" and "Washington", it outputs 'check'. What should I do so that the program will accept the space in the answer inputted by the user?
I tried searching the web but I can't understand a thing. So please help me
You can simply use getline instead of cin. cin reads the user input up until the first whitespace character (most commonly newlines or spaces), but getline will read user input until they hit enter. Because of this, if you want to get user input that includes spaces, you should use getline (or something similar) instead of cin.
Instead of
cin >> player1_answer;
you should use
getline(cin, player1_answer);
By using getline, the full user input ("George Washington") get assigned to the variable player1_answer. With cin, only "George" was being used, because it stopped listening for input after the first space.
Here is a full, working code example:
#include <iostream>
using namespace std;
string answer = "George Washington";
string player1_name = "Steve";
string player1_answer;
cout << "\t\t\t\t\t Who was the first President of United States?" << endl;
cout << "";
cout << "";
cout << "Congrats " << player1_name << " (Player1). Now, type in your answer:";
getline(cin, player1_answer); //Enter "George Washington"
if (player1_answer == answer){
cout << "check";
}else{
cout << "x";
}
//"check"
return -1;

C++ - How to know where to put cin.ignore

I have a code from my friend and we do not know how to use cin. ignore very well.
Our problem is that we are using do while and at the end of loop we want to ask user to enter if he wants to again enter some values as you will see from the code itself.
If the answer is 'y' then he can "write" again but the problem is we are using getline and we have the problem with the first getline in this loop. The program does not recognise it after the first time use.
Here is the code:
int main() {
ofstream datoteka("podaci.txt", ios::app);
if (datoteka.fail()) {
cout << "Ne postojeca datoteka";
exit(1);
}
string ime;
string prezime;
char pol;
int godiste;
float prosjek;
char odluka;
do{
system("CLS");
cout << "Unesite ime: ";
getline(cin, ime);
datoteka << ime;
cout << "Unesite prezime: ";
getline(cin, prezime);
datoteka << " " << prezime;
cout << "Unesite pol(M - musko, Z - zensko): ";
cin >> pol;
datoteka << " " << pol;
cout << "Unesite godiste: ";
cin >> godiste;
datoteka << " " << godiste;
cout << "Unesite prosjek: ";
cin >> prosjek;
datoteka << " " << prosjek << endl;
cout << endl;
cout << "Da li zelite unijeti podatke za jos jednu osobu?" << endl;
cout << "[Y] za da, [N] za ne : ";
cin >> odluka;
} while (odluka != 'N' || odluka !='n');
The problem is with the
getline(cin,ime);
It wont recognize it after the first time use.
Can someone help me?
The basic problem is that this code mixes two different forms of input. Stream extractors (operator>>) do formatted input; they skip whitespace, then try to interpret non-whitespace characters, and stop when they encounter something that doesn't fit with what they're looking for. That works fine when you have multiple extractors: std::cin >> x >> y >> z;,
getline() is an unformatted input function; it grabs whatever is in the input stream, up to the first newline.
If you mix them you can get into trouble. The usual way to get around this is to call some variation of cin.ignore() when you switch from formatted to unformatted input, and that's where the code in the question goes astray.
At the end of the loop, the code calls std::cin >> odluka;. That reads one character from the console, and leaves any additional input in place. Since the console itself typically will sit waiting for characters until it sees a newline character, typing that single character also requires hitting the Enter key, which puts a newline into the input stream. The extractor leaves the newline there. When the loop repeats, the code calls std::getline(std::cin, ime), which sees the newline character and stops reading input.
So whenever you transition from formatted input to unformatted input you have to clear out any remnants from the previous input efforts.
Or you can always read a line at a time, and parse the input yourself.
i'm not sure exactly what the problem is. i took your code and it does what it's supposed to be doing on my machine (made a few adjustments so i can understand what's going on):
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
using namespace::std;
int main() {
ofstream datoteka("podaci.txt", ios::app);
if (datoteka.fail()) {
cout << "Ne postojeca datoteka";
exit(1);
}
string ime;
string prezime;
char pol;
int godiste;
float prosjek;
// changed it to a char pointer
char odluka[] = { "Y" };
do{
system("CLS");
cout << "1: ";
getline(cin, ime);
datoteka << ime;
cout << "2: ";
getline(cin, prezime);
datoteka << " " << prezime;
cout << "3: ";
cin >> pol;
datoteka << " " << pol;
cout << "4: ";
cin >> godiste;
datoteka << " " << godiste;
cout << "5: ";
cin >> prosjek;
datoteka << " " << prosjek << endl;
cout << endl;
cout << "6" << endl;
cout << "[Y], [N]: ";
cin >> odluka;
// added this. it was not waiting for my input properly.
cin.get();
// print results
system("cls");
printf("results (press any key to move on)\n\n1: %s\n2: %s\n3: %c\n4: %d\n5: %.02f\n6: %c\n\n", ime.c_str(), prezime.c_str(), pol, godiste, prosjek, odluka);
getchar();
} while (_stricmp(odluka, "n")); // while "odluka" is not "n" or "N" (the _stricmp is not case-sensitive so they both return the same result)
system("cls");
printf("press any key to exit!\n");
getchar();
getchar();
}
here is the output from "podaci.txt":
test1 test1 1 1 1.1
test2 test2 2 2 2.2
consider using scanf/sprintf/printf with c strings in the future if this keeps malfunctioning perhaps?

Just started coding C++ [duplicate]

This question already has answers here:
Why does std::getline() skip input after a formatted extraction?
(5 answers)
Closed 3 years ago.
What seems to be the problem in my code?
When I hit Enter after entering my age, the prompt already finishes without asking for my address. I know I can use getline() for the age, but what if the user enters a non-integer answer?
Sorry, I just started coding yesterday and I want to learn the basics.
#include <iostream>
using namespace std;
int main()
{
int age;
string name, address;
cout << "Please enter the name of the user:" << endl;
getline(cin, name);
cout << "Please enter age of the user:" << endl;
cin >> age;
cout << "Please enter the address of the user:" << endl;
getline(cin, address);
cout << "Your name is " << name << " and you are " << age
<< " years old " << " who lives in " << address << endl;
cout << "Thank you for using my program!";
return 0;
}
Just add 'cin.ignore()' after 'cin>>age' like this:
cout << "Please enter age of the user:" << endl;
cin >> age;
cin.ignore();
cout << "Please enter the address of the user:" << endl;
getline(cin, address);
When getline() reads input, then a newline character is left in input stream, due to which it dosen't reads the string(address) in your program.
And if a user enters a 'float' or 'double' etc. instead of 'int' in age then it will simply extract out integer from it ,
for example:
if user enters 39.29 or 39.00005 or 39.00 or then age=39
To know more about getline check the following link:

c++ Program skips through lines while taking input [console application]

I am writing a sequential program on Library Management System which consists of two structs (books and student) and several functions.
Everything works accordingly except when I try to take console input in the function add_new_book() for the struct book , it skips line while taking input. I did research previously and then used the function cin.ignore() . That function works for the first two string inputs but after taking first two inputs, it skips the remaining input lines and terminates the function.
Here below is code from struct book and function add_new_book()
struct books{
int book_id;
string book_name;
string author_name;
string subject;
int fine;
};
void add_new_book(){
struct books b;
cout << "Enter the Book Name : ";
getline(cin, b.book_name);
cin.ignore();
//cin >> b.book_name;
cout << "Enter Author's Name : ";
getline(cin, b.author_name);
cin.ignore();
cout << "Enter Book id : ";
cin >> b.book_id;
cout << "Enter Book Cost : ";
cin >> b.fine;
cin.ignore();
cout << "Enter the Subject : ";
getline(cin, b.subject);
cout << "\n",b.book_name,b.author_name,b.book_id,b.fine,b.subject;
cout << "\n\n\t\t SUCCUSSFULLY ADDED \n";
// open a file in write mode.
ofstream outfile;
outfile.open("book1.txt");
outfile << b.book_name << endl;
outfile.close();
admin();
}
I suggest to get rid of cin.ignore's and use getline for numeric fields as well, using a std::string as a temporary buffer:
string s;
cout << "Enter Book id : ";
//cin >> b.book_id;
getline(cin, s);
Once you have the user input in a string, check its value and eventually assign it to the struct field, e.g. the book id has to be converted to int, this way:
b.book_id = std::atoi(s.c_str());
atoi will return zero if no conversion can be performed
if(b.book_id == 0)
{
cout << "Invalid book id";
}
Also, cout is not meant to be used the way you do. I would try something clean and tidy, like this:
cout << "Title : " << b.book_name << endl;
cout << "Author: " << b.author_name << endl;
//etc ...
You you shouldn't call std::cin.ignore() after std::getline(). getline will extract the '\n' from the input stream at the end of the line. Calling ignore will extract and discard another line.

C++ Won't Accept # symbol in object string? Seems to be address issue maybe?

I am so lost. I am having an issue with the following code when saving and loading data to a binary file. I have a very similar/exact piece of code that works with a different object. I think it has something to do with the email address and the # symbol in it. Here are the important functions.
/* This is my save to file function */
FILE *file=fopen("patronsave","wb");
fwrite(&buffer,sizeof(buffer),1,file);
for(int i=0;i<3;i++){
Patron_Class *ppointer = new Patron_Class();
cout << "\n" << endl;
ppointer->save(file);
}
fclose(file);
That is the function I use to save my objects to a file.
Here is my code that I am using to load the file:
vector<Patron_Class*> Patron_Entries;
FILE *file=fopen("patronsave","rb");
fread(&buffer,sizeof(buffer),1,file);
printf("Buffer: %d\n",buffer);
for(int i=0;i<buffer;i++){
Patron_Class *pointer2 =new Patron_Class(file);
Patron_Entries.push_back(pointer2);
Patron_Entries[i] -> print();
system("pause");
}
fclose(file);
If I run the save function and then immediatly run the load function it works, but if I only run the load function it crashes when it tried to load the email. Here is my class and object code:
class Patron_Class{
public:
long patron_id;
string F_name;
string L_name;
long phone_num;
string email;
string street_address;
string city;
string state;
int zip_code;
Patron_Class(){
cout << "Please enter a new ID" << endl;
cin >> patron_id;
cin.ignore(1000, '\n');
system("cls");
cout << "Please enter a First name" << endl;
cin >> F_name;
cin.ignore(1000, '\n');
system("cls");
cout << "Please enter a last name" << endl;
cin >> L_name;
cin.ignore(1000, '\n');
system("cls");
cout << "Please enter a phone number" << endl;
cin >> phone_num;
cin.ignore(1000, '\n');
system("cls");
cout << "Please enter a email" << endl;
cin >> email;
cin.ignore(1000, '\n');
system("cls");
cout << "Please enter a street address" << endl;
cin >> street_address;
cin.ignore(1000, '\n');
system("cls");
cout << "Please enter a city" << endl;
cin >> city;
cin.ignore(1000, '\n');
system("cls");
cout << "Please enter a State via it's initials" << endl;
cin >> state;
cin.ignore(1000, '\n');
system("cls");
cout << "Please enter a zip code" << endl;
cin >> zip_code;
cin.ignore(1000, '\n');
system("cls");
cout << "You have created a new patron named: " << F_name << " " << L_name << endl;
}
Patron_Class(FILE *inputfile){
fread(&patron_id, sizeof(patron_id),1,inputfile);
fread(&F_name, sizeof(F_name),1,inputfile);
fread(&L_name, sizeof(L_name),1,inputfile);
fread(&phone_num, sizeof(phone_num),1,inputfile);
fread(&email, sizeof(email),1,inputfile);
fread(&street_address, sizeof(street_address),1,inputfile);
fread(&city, sizeof(city),1,inputfile);
fread(&state, sizeof(state),1,inputfile);
fread(&zip_code, sizeof(zip_code),1,inputfile);
}
void print(){
cout << patron_id << " " << F_name << " " << L_name << " " << phone_num << " " << email << " " << street_address << " " << city << " " << state << " " << zip_code << "\n" << endl;
}
void save(FILE *inputFile){
fwrite(&patron_id, sizeof(patron_id),1,inputFile);
fwrite(&F_name, sizeof(F_name),1,inputFile);
fwrite(&L_name, sizeof(L_name),1,inputFile);
fwrite(&phone_num, sizeof(phone_num),1,inputFile);
fwrite(&email, sizeof(email),1,inputFile);
fwrite(&street_address, sizeof(street_address),1,inputFile);
fwrite(&city, sizeof(city),1,inputFile);
fwrite(&state, sizeof(state),1,inputFile);
fwrite(&zip_code, sizeof(zip_code),1,inputFile);
}
};
Does anyone know why it might be crashing?
This is CLEARLY wrong:
string F_name;
...
fread(&F_name, sizeof(F_name),1,inputfile);
...
fwrite(&F_name, sizeof(F_name),1,inputFile);
[The same applies to all the other strings in your PatronClass - I'm using the first one for this example]
The class std::string will look something like this (for illustration purposes, the exact implementation involves several layers, some templates, and other stuff, so this is simplified for the purposes of the explanation to follow):
class string
{
char *str;
int len;
public:
...
};
So, when you do fread from the file and fwrite to the file, you are reading/writing the char *str; and int len; members from/to the file.
Let's say we start your program from scratch, with no data in the file, and we use the Patron_Class() constructor. So we read in an id, and then the F_name from the console. Let's say we enter Charles. So somehow the string class will allocate 8 bytes of memory, at the address of 0x600018. So string::str == 0x600018 and len = 8 - at location 6000018 in the heap are the letters C h a r l e s \0 [ spaces just to illustrate they are in separate memory locations]. Now we save this to a file. So the file contains 00600018 00000008. Now we stop the program and start it again, using the PatronClass(file) constructor. The heap is completely empty. We load the file data, so string::str = 0x600018 and len = 8, but that locaton 0x600018 does not contain C h a r l e s \0, but whatever the heap normally is filed with when the heap is initialized [quite likely 0]. So no wonder your name doesn't appear.
Now, the exact behaviour of your actual program is probably not the same as what I've described above, but it will NOT work right. No way, never, ever. No matter what characters you have or haven't got in names, email addresses or any other string in your code. The only reason it may APPEAR to work is that the data is still, for the most part, there in the heap, and it seems to be working because it doesn't get overwritten by something else in your case.