I've seen other questions about this problem but I can't seem to incorporate those in my problem right here.
My Code
cout << "Get User's input\n";
for (int i = 0; i < size; i++)
{
cout << "Enter the author's name: ";
cin.ignore();
getline(cin,a[i].name); // Ariel the Mermaid
cout << endl;
for (int count = 0; count < size; count++)
{
cout << "Enter Title " << count + 1 << " : ";
cin.ignore();
getline(cin,a[i].books[count].title); // Intro to Me
if (a[i].books[count].title == "NONE")
break;
cout << "Enter Price " << count + 1 << " : $";
cin >> a[i].books[count].price; // 49.99
}
cout << endl;
}
When I have inputted "Ariel the Mermaid", it gives me "riel the Mermaid" when I cout it. Also the "Intro to Me" gives "ntro to Me".
What's the problem with this code?
You are skipping the first character with cin.ignore().
A good use of cin.ignore() is when you have cin >> before a getline()
for example:
cout << "Digit you age" << endl;
cin >> age;
cout << "Digit your full Name" << endl;
cin.ignore();
getline(cin,name);
This happens because when the compiler reachs the cin will make a stop to read from the keyboard until you pressed the enter key to finish, then the getline() will capture the last character wich is a "\n". So you have to cin.ignore() to ignore that last character.
Your call to cin.ignore() is ignoring one character. This method ignores a count of n characters provided as an argument. The default n is 1.
You should delete the line with cin.ignore ().
Related
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.
int main () {
const int MAX_INPUT = 99;
string names[MAX_INPUT];
string eraseName;
string newList;
int numNames = 0;
int i = 0;
cout << "How many names do you want (max 99)? ";
cin >> numNames;
do {
if(numNames > MAX_INPUT) {
cout << "Out of memory!" << endl;
break;
}
cout << "Enter name #" << (i+1) << ": ";
cin.ignore();
getline(cin,names[i]);
++i;
}
while (i < numNames);
cout << "What name do you want to eliminate? ";
getline(cin,eraseName);
cout << "Here is the list in reverse order, skipping ";
cout << eraseName << "..." << endl;
i = 0;
for (i = 0; i < numNames; ++i) {
cout << names[i] << endl;
}
return 0;
}
I have an assignment where I have to "eliminate" an element in an array and recreate the output. I know my final for loop will not erase the element, it's just there because I was testing the issue, but if names has two inputs (John Doe and Jane Doe) and I say to cout them the final loop couts:
John Doe
ane Doe
Move cin.ignore() right after cin >> numNames;, before the loop that reads the names.
You only need this to ignore the newline that is left in the stream after reading the number of names. getline() reads (and ignores) the newline from the stream, so there's no need to call ignore() again before reading each name. As a result, it's reading and ignoring the first character of the name.
The following block of code
if(numNames > MAX_INPUT) {
cout << "Out of memory!" << endl;
break;
}
does not need to be executed in every iteration of the do-while loop. You can change you function to use:
if(numNames > MAX_INPUT) {
cout << "Out of memory!" << endl;
// Deal with the problem. Exit??
}
do {
cout << "Enter name #" << (i+1) << ": ";
cin.ignore();
getline(cin,names[i]);
++i;
} while (i < numNames);
Once you move the check out of the loop, you have to ask yourself, "Do I need to ignore a character in each iteration of the loop?" The answer is "No". You need to ignore the newline only after reading numNames. So, you move it out of the loop also.
if(numNames > MAX_INPUT) {
cout << "Out of memory!" << endl;
// Deal with the problem. Exit??
}
// Ignore the newline left on the stream before reading names.
cin.ignore();
do {
cout << "Enter name #" << (i+1) << ": ";
getline(cin,names[i]);
++i;
} while (i < numNames);
You can improve on that by making sure that everything up to and including the newline is ignored by using:
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Add
#include <limits>
to be able to use std::numeric_limits.
Alright, I wrote a game of hangman. The game works great, except after the user finishes the game, and enters the char value of Y to play again.
I have traced the problem down to the getline() function at the start of my do-while loop. If I enter Y, then the do-while loop succesfully repeats, but the getline function seems to already think that there is input in cin, even though I don't enter anything.
Here is my code so far:
#include<iostream>
#include<string>
using namespace std;
int main() {
string secretWord;
string secretWordClean = "";
string guessedLetters; //to be loaded with _ characters equal to length of secretWord
string incorrectlyGuessedChars = "";
char individualCharGuess;
char playAgain;
size_t countOfLetters = 0; //begine count at 0
size_t guessesRemaining;
int guessedUsed;
begin_game://label which we can use to bring us back to the start of the do-while loop at any time
do{//start of the game
cout << "Please enter a secret word: ";
getline(cin, secretWord); //y getline is cuaing the issue
for(int i = 0; i < secretWord.length(); i++){
if (isalpha(secretWord[i])){
secretWordClean += secretWord[i];
}
}
secretWord = secretWordClean; //assign all alpha secret word string back to original variable for better readability
guessesRemaining = secretWord.length() * 2;
for(int i = 0; i < secretWord.length(); i++){
guessedLetters += "_"; //fills guessedLetters with blanks equal to the length of the secretWord
}
cout << "Please guess a letter, you have " << guessesRemaining << " guesses remaining!" << endl;
cin >> individualCharGuess;
for(int i = 0; i < secretWord.length(); i++){ //every complete iteration of this for loop = one single guess
if(secretWord[i] == individualCharGuess){
guessedLetters[i] = individualCharGuess; //will replace the spaces with the correct character, if guessed
countOfLetters++; //if any letter is guessed correctly, this indicator will be inrimented above 0
continue;
}
if(secretWord.find(individualCharGuess) == string::npos){
if(incorrectlyGuessedChars.find(individualCharGuess) == string::npos){
incorrectlyGuessedChars += individualCharGuess;
}
}
}
if(secretWord.compare(guessedLetters) == 0){
cout << "You win! The word was: " << secretWord << endl;
guessedUsed = ((secretWord.length() * 2) - guessesRemaining) + 1 ;
cout << "You used " << guessedUsed << " guesses." << endl;
cout << "Play again? Enter Y for Yes, or anything else to exit: ";
cin >> playAgain;
if(playAgain != 'Y'){
break; //exit the loop if user guesses all the letters and doesn't want to play again
}
else {
goto begin_game;
}
}
guessesRemaining--; //we decriment our total guesses remaining if the user does not win the game or run out of guesses
if(countOfLetters > 0){
cout << "You have correctly guessed a letter!" << endl;
cout << "Here are the letters you have guessed correctly so far: ";
cout << guessedLetters << endl;
cout << "Here are the letters you have guessed incorrectly so far: ";
cout << incorrectlyGuessedChars << endl;
countOfLetters = 0; //reset the counter to prepare for next iteration of do-while loop
}
else if (guessesRemaining <= 0) {
cout << "You have run out of guesses!" << endl;
cout << "Here are the letters that you guessed correctly: ";
cout << guessedLetters << endl;
cout << "Here are the letters you guessed incorrectly: ";
cout << incorrectlyGuessedChars << endl;
cout << "The secret word was: " << secretWord << endl;
cout << "Play again? Enter Y for Yes, or anything else to exit: ";
cin >> playAgain;
if(playAgain != 'Y'){
break; //exit the loop if user guesses all the letters and doesn't want to play again
}
else goto begin_game;
}
else {
cout << "You guessed wrong! Keep trying, " << guessesRemaining << " guesses to go!" << endl;
cout << "Here are the letters you have guessed correctly so far: ";
cout << guessedLetters << endl;
cout << "Here are the letters you have guessed incorrectly so far: ";
cout << incorrectlyGuessedChars << endl;
}
}while (secretWord.compare(guessedLetters) != 0 || guessesRemaining != 0); //use to repeat the request for a single char guess
return 0;
}
You are mixing formatted and unformatted I/O: reading a character will stop immediately after reading the character. Since after entering the character you entered a newline the newline still sticks in the stream, read for getline() to terminate the line. You should skip leading whitespace before using std::getline(), e.g.:
if (std::getline(std::cin >> std::ws, s)) {
...
}
Alternatively, you could use ignore() to ignore all characters up to and including the newline. Note that ignoring just one character won't work reliably as a sequence of spaces between the '\n'. To use ignore() you should use the proper magic number instead:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
BTW, you should also always verify that input was actually successful as you'd otherwise easily get incorrect behavior when it isn't.
Don't mix token extraction using >> and line extraction using getline. The former doesn't remove newlines, so the next getline call after token extraction may end up reading the remaining bit of the previous line, which may be an empty string.
If you must mix the two kinds of input, use std::cin >> std::ws to gobble up stray whitespace (including the newline) before using getline.
In the below code, I'm running into an error when I try to get the user to input their name. My program just skips it over and goes right over to making the function calls without allowing the user to enter their name. Despite the error, my program is compiling. I'm not sure what's going wrong as I wrote that part based off other examples I found on here. Any suggestions?
#include <iostream>
#include <string>
#include <time.h>
using namespace std;
char showMenu();
void getLottoPicks(int[]);
void genWinNums(int[]);
bool noDuplicates(int[]);
const int SIZE = 7;
int main()
{
int userTicket[SIZE] = {0};
int winningNums[SIZE] = {0};
char choice;
string name;
srand(time(NULL));
do
{
choice = showMenu();
if (choice == '1')
{
cout << "Please enter your name: " << endl;
getline(cin, name);
getLottoPicks(userTicket);
genWinNums(winningNums);
for (int i = 0; i < SIZE; i++)
cout << winningNums[i];
}
} while (choice != 'Q' && choice != 'q');
system("PAUSE");
return 0;
}
Added the code for showMenu:
char showMenu()
{
char choice;
cout << "LITTLETON CITY LOTTO MODEL:" << endl;
cout << "---------------------------" << endl;
cout << "1) Play Lotto" << endl;
cout << "Q) Quit Program" << endl;
cout << "Please make a selection: " << endl;
cin >> choice;
return choice;
}
And getLottoPicks (this part is very wrong and I'm still working on it):
void getLottoPicks(int numbers[])
{
cout << "Please enter your 7 lotto number picks between 1 and 40: " << endl;
for (int i = 0; i < SIZE; i++)
{
cout << "Selection #" << i + 1 << endl;
cin >> numbers[i];
if (numbers[i] < 1 || numbers[i] > 40)
{
cout << "Please choose a number between 1 and 40: " << endl;
cin >> numbers[i];
}
if (noDuplicates(numbers) == false)
{
do
{
cout << "You already picked this number. Please enter a different number: " << endl;
cin >> numbers[i];
noDuplicates(numbers);
} while (noDuplicates(numbers) == false);
}
}
}
After doing cin >> choice; inside char showMenu(), if a user inputs 1[ENTER], the char consumes 1 character from cin, and the newline stays inside the stream. Then, when the program gets to getline(cin, name);, it notices that there's still something inside cin, and reads it. It's a newline character, so getline gets it and returns. That's why the program is behaving the way it is.
In order to fix it - add cin.ignore(); inside char showMenu(), right after you read the input. cin.ignore() ignores the next character - in our case, the newline char.
And a word of advice - try not to mix getline with operator >>. They work in a slightly different way, and can get you into trouble! Or, at least remember to always ignore() after you get anything from std::cin. It may save you a lot of work.
This fixes the code:
char showMenu()
{
char choice;
cout << "LITTLETON CITY LOTTO MODEL:" << endl;
cout << "---------------------------" << endl;
cout << "1) Play Lotto" << endl;
cout << "Q) Quit Program" << endl;
cout << "Please make a selection: " << endl;
cin >> choice;
cin.ignore();
return choice;
}
from looking at code showMenu function has problem. and it's not returning asccii equivalent of '1' that is: 31 integer. try printing value returned by showmenu. you will get that
UPDATE:
It is because cin in delimited by ' '(whitespace) and getline by '\n' character, so when enter name and press enter cin in showmenu will consume whole string except '\n' from istream and that is read by getline. to see this when it ask for choice enter string like 1 myname (1 whitespace myname)and press ENTER will display name. now cin will read 1 in choice and myname in name by getline.
This question already has answers here:
Why does std::getline() skip input after a formatted extraction?
(5 answers)
Closed 9 years ago.
This is a very strange problem, when my program asks the user for the address, instead of waiting for input, it seems to skip the getline() function completely
Answerinput:
cout << "would you like to add another entry to the archive? (Y/N):";
cin >> answer;
cout << endl;
cout << endl;
answer = toupper(answer);
switch(answer)
{
case 'Y':
Entrynumber++;
cout << "began record number " << Entrynumber << "+ 1." << endl;
cout << "Enter the last name of the person to be entered" << endl;
cin >> stringentry;
cout << endl;
stringlength = stringentry.length();
strcpy(Record[Entrynumber].Last_Name, stringentry.c_str());
Record[Entrynumber].Last_Name[stringlength] = '*';
cout << "Enter the first name of the person" << endl;
cin >> stringentry;
cout << endl;
stringlength = stringentry.length();
strcpy(Record[Entrynumber].First_Name, stringentry.c_str());
Record[Entrynumber].First_Name[stringlength] = '*';
cout << "Enter the SSN of the person" << endl;
cin >> Record[Entrynumber].SSN;
cout << endl;
cout << "Enter the age of the person" << endl;
cin >> Record[Entrynumber].Age;
cout << endl;
cout << "Enter the address of the person" << endl;
cin.getline(Record[Entrynumber].Address,70);
cout << endl;
stringentry = Record[Entrynumber].Address;
stringlength = stringentry.length();
Record[Entrynumber].Address[stringlength] = '*';
cout << "you entered:" << endl;
for(jim = 0 ; Record[Entrynumber].Last_Name[jim + 1] != '*' ; jim++)
{
cout << Record[Entrynumber].Last_Name[jim];
}
cout << ',' ;
for(jim = 0 ; Record[Entrynumber].First_Name[jim + 1] != '*' ; jim++)
{
cout << Record[Entrynumber].First_Name[jim];
}
cout << endl;
cout << Record[Entrynumber].SSN << endl;
cout << Record[Entrynumber].Age << endl;
for(jim = 0 ; Record[Entrynumber].Address[jim + 1] != '*' ; jim++)
{
cout << Record[Entrynumber].Address[jim];
}
cout << endl;
cout << endl;
goto Answerinput;
case 'N':
cout << "ok" << endl;
break;
default:
cout << "invalid answer" << endl;
goto Answerinput;
}
output to console
would you like to add another entry to
the archive? (Y/N):Y
began record number 6+ 1.
Enter the last name of the person to be entered
John
Enter the first name of the person
John
Enter the SSN of the person 22222222
Enter the age of the person 22
Enter the address of the person
you entered:
Joh,Joh
22222222
22
*¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
//////////////22 more lines of'|'//////////////////////////////////////////////
...
¦¦¦¦¦¦¦¦l3-j
would you like to add another entry to the archive? (Y/N):
Both cin.getline() and getline() do the same thing.
I'm using MVC++ 2008.
All of the fields in the Record array are structs, Record[Entrynumber].Address is a char array.
Cin is probably leaving the carriage return in the buffer which getline retrieves. Try
cin.ignore(1000, '\n');
cin.getline(Record[Entrynumber].Address,70);
The >> operator doesn't remove the newline character after retrieving data, but ignores leading whitespace before retrieving data, while getline just retrieves whatever is in there, and removes the '\n' after reading as it is apart of the line it is 'getting'.
Seeing as how there might be input left over in the buffer which your getline is reading first, I'd suggest you clear the buffer before trying to input the next data:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');