why while loop do not need user to input in c++ - c++

I'm learning c++ and reading c++ primer plus, but I don't understand why this code need two "cin >> ch". I know the first cin will read character that was user input.but then I delete first "cin >> ch" and run code ,the program have no error.So the fist cin is necessary? why the second cin needn't user to input?
#include <iostream>
int main()
{
using namespace std;
char ch;
int count = 0;
cout << "Enter characters; enter # to quit:\n";
cin >> ch; //get a character
while (ch != '#')
{
cout << ch;
++count;
cin >> ch; // get the next character
}
cout << endl << count << " characters read\n";
return 0;
}

You can evaluate your input right inside condition of while loop.
#include <iostream>
int main()
{
char ch;
int count = 0;
std::cout << "Enter characters; enter # to quit:\n";
while (std::cin >> ch && ch != '#')
{
std::cout << "entered: " << ch << std::endl;
++count;
}
std::cout << std::endl << count << " characters read" << std::endl;
return 0;
}
When while condition is entered it will wait for you to enter anything first. Once input is received it will check if the input is not #. If input is not # the loop is entered, input printed out, counter increased, and back to waiting for another input. If # is entered, condition becomes false, and loop is aborted.

If you remove the first cin then count will never be incremented. The user can enter # character before entering the loop and the program can never enter it therefore.

The first cin>>ch is obviously used to take input from user but you
have again accepting data in while loop using the same variable name "ch" ,
So when you run the program it will not give u error but accept only first value that you have accept before the while loop not in while loop.
In while loop you can assign new value to variable "ch" but not accept the new value again.

Related

Infinite loop created when inputting "yy" into a char variable that should only take a single character such as 'y' or 'n', "nn" does not break code

The code in the cont function asks the user if they want to play my game again.
The code works when receiving proper character inputs such as 'y' or 'n' as well as their respective capital letter variants, and the else block works properly to loop the function if an invalid input such as 'a' or 'c' is entered.
However during a test run, an input of 'yy' breaks the code causing the program to infinitely loop, running not only this cont function but my game function as well.
choice is stored as a char variable. I am wondering why the code even continues to run upon inputting multi-character inputs such as 'yy' or 'yes'. What's interesting is 'nn', 'ny' and other variations of multi-character inputs that begin with 'n' causes no issues and properly results in the else if block running as intended. Which prints "Thanks for playing." then ends the program.
Can variables declared as char accept inputs greater than 1 character? Does it only take the first value? And if so why does 'yy' cause a loop rather than the program running as intended by accepting a value of 'y' or 'Y'? How can I change my program so that an input of 'yy' no longer causes issues, without specific lines targeting inputs such as 'yy' or 'yes'.
#include <iostream>
#include <string> // needed to use strings
#include <cstdlib> // needed to use random numbers
#include <ctime>
using namespace std;
// declaring functions
void cont();
void game();
void diceRoll();
// variable declaration
string playerName;
int balance; // stores player's balance
int bettingAmount; // amount being bet, input by player
int guess; // users input for guess
int dice; // stores the random number
char choice;
// main functions
int main()
{
srand(time(0)); // seeds the random number, generates random number
cout << "\n\t\t-=-=-= Dice Roll Game =-=-=-\n";
cout << "\n\nWhat's your name?\n";
getline(cin, playerName);
cout << "\nEnter your starting balance to play with : $";
cin >> balance;
game();
cont();
}
// function declaration
void cont()
{
cin >> choice;
if(choice == 'Y' || choice == 'y')
{
cout << "\n\n";
game();
}
else if (choice == 'N' || choice == 'n')
{
cout << "\n\nThanks for playing.";
}
else
{
cout << "\n\nInvalid input, please type 'y' or 'n'";
cont(); // calls itself (recursive function!!!)
}
}
void game()
{
do
{
cout << "\nYour current balance is $ " << balance << "\n";
cout << "Hey, " << playerName << ", enter amount to bet : $";
cin >> bettingAmount;
if(bettingAmount > balance)
cout << "\nBetting balance can't be more than current balance!\n" << "\nRe-enter bet\n";
} while(bettingAmount > balance);
// Get player's numbers
do
{
cout << "\nA dice will be rolled, guess the side facing up, any number between 1 and 6 : \n";
cin >> guess;
if(guess <= 0 || guess > 6 )
{
cout << "\nYour guess should be between 1 and 6\n" << "Re-enter guess:\n";
}
} while(guess <= 0 || guess > 6);
dice = rand() % 6+1;
diceRoll();
if (dice == guess)
{
cout << "\n\nYou guessed correctly! You won $" << (bettingAmount * 6);
balance = balance + (bettingAmount * 6);
}
else
{
cout << "\n\nYou guessed wrong. You lost $" << bettingAmount << "\n";
balance = balance - bettingAmount;
}
cout << "\n" << playerName << ", you now have a balance of $" << balance << "\n";
if (balance == 0)
{
cout << "You're out of money, game over";
}
cout << "\nDo you want to play again? type y or n : \n";
cont();
}
void diceRoll()
{
cout << "The winning number is " << dice << "\n";
}
Does it only take the first value?
Yes, the >> formatted extraction operator, when called for a single char value, will read the first non-whitespace character, and stop. Everything after it remains unread.
why does 'yy' cause a loop
Because the first "y" gets read, for the reasons explained above. The second "y" remains unread.
This is a very common mistake and a misconception about what >> does. It does not read an entire line of typed input. It only reads a single value after skipping any whitespace that precedes it.
Your program stops until an entire line of input gets typed, followed by Enter, but that's not what >> reads. It only reads what it's asked to read, and everything else that gets typed in remains unread.
So the program continues to execute, until it reaches this part:
cin >> bettingAmount;
At this point the next unread character in the input is y. The >> formatted extraction operator, for an int value like this bettingAmount, requires numerical input (following optional whitespace). But the next character is not numerical. It's the character y.
This results in the formatted >> extraction operator failing. Nothing gets read into bettingAmount. It remains completely unaltered by the >> operator. Because it is declared in global scope it was zero-initialized. So it remains 0.
In addition to the >> extraction operator failing, as part of it failing it sets the input stream to a failed state. When an input stream is in a failed state all subsequent input operation automatically fail without doing anything. And that's why your program ends up in an infinite loop.
Although there is a way to clear the input stream from its failed state this is a clumsy approach. The clean solution is to fix the code that reads input.
If your intent is to stop the program and enter something followed by Enter then that's what std::getline is for. The shown program uses it to read some of its initial input.
The path of least resistance is to simply use std::getline to read all input. Instead of using >> to read a single character use std::getline to read the next line of typed in input, into a std::string, then check the the string's first character and see what it is. Problem solved.
cin >> bettingAmount;
And you want to do the same thing here. Otherwise you'll just run into the same problem: mistyped input will result in a failed input operation, and a major headache.
Why do you need this headache? Just use std::getline to read text into a std::string, construct a std::istringstream from it, then use >> on the std::istringstream, and check its return value to determine whether it failed, or not. That's a simple way to check for invalid input, and if something other than numeric input was typed in here, you have complete freedom on how to handle bad typed in input.

This code is not running properly

I tried to run the following code but after one input, the rest of the input is initialized to zero and is displayed on the screen automatically. where did I go wrong?
#include<iostream>
#define N 50
using namespace std;
struct movies_t
{
char title[60];
int year;
}user[N];
void printmovie(movies_t);
int main()
{
for(int i = 0; i < N; i++)
{
cout << "Enter title: ";
cin.get(user[i].title, 60);
cout << "Enter year: ";
cin >> user[i].year;
}
cout << "\nYou have entered these movie: \n";
for(int i = 0; i < N; i++)
printmovie(user[i]);
return 0;
}
void printmovie(movies_t m)
{
cout << m.title;
cout << " (" << m.year << ")\n";
}
The problem is that when you press enter after inputting the year for the first movie, that enter (newline) is still in the input buffer, so when you next call cin.get(...) it will read that newline and think you entered an empty line.
You need to tell cin to ignore the rest of the line including the newline.
After execution of
cin >> user[i].year;
the newline character is still left in the input stream.
The next time you execute
cin.get(user[i].title, 60);
the first character encountered is the newline character. When that happens, failbit of cin is set. Here's some info from http://en.cppreference.com/w/cpp/io/basic_istream/get (emphasis mine):
4) Reads characters and stores them into the successive locations of the character array whose first element is pointed to by s. Characters are extracted and stored until any of the following occurs:
n-1 characters have been stored
end of file condition occurs in the input sequence (setstate(eofbit) is called)
the next available input character c equals delim, as determined by Traits::eq(c, delim). This character is not extracted (unlike basic_istream::getline())
If no characters were extracted, calls setstate(failbit). In any case, if count>0, a null character (CharT() is stored in the next successive location of the array.
After the failbit of cin is set, nothing is read from cin until the state is cleared by an explicit call to cin.clear().
Since you don't have any code to check the state of cin and clear the state when appropriate, nothing is read in the loop after the first iteration.
One way to fix the problem is add a line to ignore the contents of the stream after the year is read.
cin >> user[i].year;
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Also, it is a good practice to always check the state of a stream after an IO operation to make sure that you don't overlook any errors.
for(int i = 0; i < N; i++)
{
cout << "Enter title: ";
cin.get(user[i].title, 60);
if ( !cin )
{
cout << "Error reading title.\n";
exit(1);
}
cout << "Enter year: ";
cin >> user[i].year;
if ( !cin )
{
cout << "Error reading name.\n";
exit(1);
}
// Ignore everything up to and including the newline character.
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}

do loop statement is causing an infinite loop

I am writing a library program that displays a menu of options letting the user add new books to the library, but in my add statement it accepts the title and then gets caught in an infinite loop. I wrote a book class that mainly uses pointers to assign things, if I need to post that I will. But when you run the program it compiles, displays the menu, and when you choose add a book it accepts the title but as soon as you hit enter it starts an a infinite loop.
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
using namespace std;
int main()
{
int bookCounter = 0;
Book library[25];
int menuOption = 0;
char tempt[50] = "\0";
char tempauth[50] = "\0";
char search[50] = "\0";
unsigned int tempp = 0;
do
{
menuOption = 0;
cout << endl << "1. Show the Library" << endl;
cout << "2. Add a Book" << endl;
cout << "3. Search the Library by Title" << endl;
cout << "4. Exit Library" << endl;
cout << "Select a menu option (e.g. 1, 2, etc.): ";
cin >> menuOption;
if(menuOption == 1)
{
for(int i = 0; i < bookCounter; i++)
{
library[i].displayBook();
}
}
else if(menuOption == 2)
{
cout << "Enter the Title: ";
cin >> tempt[50];
cout << endl << "Enter the Author's name: " ;
cin >> tempauth[50];
cout << endl << "How many pages does the book have? (just enter a number, e.g. 675, 300): ";
cin >> tempp;
library[bookCounter].setAuthor(tempauth);
library[bookCounter].setTitle(tempt);
library[bookCounter].setPages(tempp);
bookCounter++;
menuOption = 0;
}
else if(menuOption == 3)
{
cout << "Enter a title you would like search for (will return partial matches): ";
cin >> search[50];
for (int i = 0; i < bookCounter; i++)
{
int temp = strcmp(search, library[i].getTitle());
if (temp == 1)
{
library[i].displayBook();
}
}
}
}while(menuOption != 4);
system("pause");
return 0;
}
The problem is caused by the way you are trying to read into the arrays:
cin >> tempt[50];
This tries to read a single character into the character at index 50 of the array tempt, which is outside the bounds of the array (which has valid indices in the range [0,49]).
This means only the first character of the entered title will be consumed from the output. Similarly for author. Hence, only the first two characters which you have entered are actually read. Then, this line will be encountered:
cin >> menuOption;
Here, what is left in the buffer (the remainder of the title) will be read, expecting a number. As this does not match a valid format for a number, you will get an error flag in cin. This will mean that all resulting inputs will also fail, menuOption will never change and your program gets stuck in a loop.
A solution to your problem would be to read into tempt without index. You can also check if a read has failed using if(cin.fail()) which should only trigger if there's been an error. If so, handle it and then call cin.clear() to reset the error flags.
I think that this line cause the problem,
cin >> search[50];
You're accessing out bound of search array.
One error is when you type in the menu option, the 'return' stays in the input buffer. The next read of char[] in your tempt variable, will be skipped.
Type cin.ignore(); after cin >> menuOption;
Also, you should read tempt instead instead of tempt[50].
This
cin >> tempt[50];
accesses a non-existent entry in the array. You probably meant to code
cin >> tempt;
Or, better, use std::string instead of raw char array.

do while loops can't have two cin statements?

I'm just following a simple c++ tutorial on do/while loops and i seem to have copied exactly what was written in the tutorial but i'm not yielding the same results. This is my code:
int main()
{
int c=0;
int i=0;
int str;
do
{
cout << "Enter a num: \n";
cin >> i;
c = c + i;
cout << "Do you wan't to enter another num? y/n: \n";
cin >> str;
} while (c < 15);
cout << "The sum of the numbers are: " << c << endl;
system("pause");
return (0);
}
Right now, after 1 iteration, the loop just runs without asking for my inputs again and only calculating the sum with my first initial input for i.
However if i remove the second pair of cout/cin statements, the program works fine..
can someone spot my error please? thank you!
After you read the string with your cin >> str;, there's still a new-line sitting in the input buffer. When you execute cin >> i; in the next iteration, it reads the newline as if you just pressed enter without entering a number, so it doesn't wait for you to enter anything.
The usual cure is to put something like cin.ignore(100, '\n'); after you read the string. The 100 is more or less arbitrary -- it just limits the number of characters it'll skip.
If you change
int str;
to
char str;
Your loop works as you seem to intend (tested in Visual Studio 2010).
Although, you should also probably check for str == 'n', since they told you that they were done.
...and only calculating the sum with my first initial input for i...
This is an expected behavior, because you are just reading the str and not using it. If you enter i >= 15 then loop must break, otherwise continues.
I think you wanted this thing
In this case total sum c will be less than 15 and continue to sum if user inputs y.
#include<iostream>
using namespace std;
int main()
{
int c=0;
int i=0;
char str;
do
{
cout << "Enter a num: \n";
cin >> i;
c = c + i;
cout << "Do you wan't to enter another num? y/n: \n";
cin >> str;
} while (c < 15 && str=='y');
cout << "The sum of the numbers are: " << c << endl;
return 0;
}

While keeps repeating on letters but not on #'s

I have a while loop here that only takes in 1 and 2 as the number, if i insert and number that is not these my else statement will keep asking for the correct one, which works correctly. But if i insert a letter my else statement loops forever. How can i fix this?
#include <iostream>
using namespace std;
int main()
{
int myChoice;
cin >> myChoice;
while ( myChoice >= 2 || myChoice <= 1)
{
if (myChoice == 1)
{
cout <<"food1";
break;
}
else if (myChoice == 2)
{
cout <<"food2";
break;
}
else
{
cout << " " << endl;
cout << "Please select the proper choices" << endl;
cout << "Try again: ";
cin >> myChoice;
}
}
return 0;
}
If you enter a non-number, then cin >> myChoice fails. That means that it leaves the input intact in the input buffer and when you get there again it tries to parse it and fails, and so on... You must clear the error state and ignore the non-digits. The simplest way is something like this:
cout << "Try again: ";
cin.clear(); // clear error state
cin.ignore(std::numeric_limits<streamsize>::max(), '\n'); // ignore till the end of line
cin >> myChoice;
The problem here is that the cin >> operator expects to receive an int input and receives a char input.
The istream module, of which cin is an instance, is using buffered I/O. This means that the user input is first stored in a buffer, and then read from that buffer when the user program accesses the >> operator. Ordinarily, if the >> operator succeeds in reading and parsing the user input, the read data is extracted from the buffer and the next invocation of the >> operator would continue where the last call left off. In you case, however, the >> operator attempts to parse the user input as a number and fails since it contains illegal chars which are not digits. The >> operator doesn't extract the read data from the buffer in this case and this same data is being referred to over and over again in the following calls to the >> operator.
You should empty the buffer on failure, the way ybungalobill suggested, for instance.
Your while condition is always true, then you use break to exit the loop. You could simplify things a bit like this:
#include <iostream>
using namespace std;
int main()
{
int myChoice;
cin >> myChoice;
while( myChoice != 1 || myChoice != 2 ) {
cout << endl;
cout << "Please select the proper choices" << endl;
cout << "Try again: ";
cin.clear();
cin.ignore(std::numeric_limits<streamsize>::max(), '\n');
cin >> myChoice;
}
// At this point myChoice is 1 or 2
if (myChoice == 1)
cout << "food1";
else if (myChoice == 2)
cout << "food2";
}