Using a space for canceling a simple loop - c++

Here is my code for this simple assignment:
Write the code that will read character input from the user until a blank (a space) is entered. Print how many characters were entered. Keep in mind the user may decide to enter a blank as his first character.
Why is the space not ending the loop?
#include <iostream>
using namespace std;
int main(){
char answer;
int count=1;
do{
cout << "please enter number " << count;
cin >> answer;
count++;
}while(answer!=' ');
cout << "you entered " << count-1 << "numbers." << endl;
return 0;
}

The cin >> operations skip all kinds of whitespace by default. You can use cin >> noskipws; before your loop to disable whitespace skipping or use cin.get() instead:
cin.get(answer);
You should be aware that newlines and carriage returns are no longer skipped now, so you have to handle them separately. Also, you should check the stream status to react to end-of-file:
do {
cout << "Please enter number " << count << endl;
do {
cin.get(answer);
} while (cin && (answer == '\r' || answer == '\n'));
count++;
} while (cin && answer != ' ');

Related

Using a while loop to check for input errors within a switch case

I have a switch in which one case asks the user for several inputs to use for constructing a class object. One of these inputs should be in the form of a number. If a number is not entered it breaks the switch and ends up terminating the program. I want to set up a while(){} condition so that if a non integer is entered it will prompt the user to enter an integer and then continue on with the program.
int main(){
int in_yob, ranking;
string in_first_name, in_last_name, in_genre, in_fact, last_name, in_composer;
char selection, choice;
do {
DisplayMenu();
cin >> selection;
cout << endl;
while (!cin || selection < 48 || selection > 53){
cin.clear();
cout << "Please make a valid selection" << endl;
DisplayMenu();
cin >> selection;
}
switch (selection) {
case 49 : {
cout << "First Name: ";
cin >> in_first_name;
cout << "Last Name: ";
cin >> in_last_name;
cout << "Genre: ";
cin >> in_genre;
cout << "Year of Birth: ";
cin >> in_yob;
cout << "Fact: ";
cin >> in_fact;
last_name = in_last_name;
transform(last_name.begin(), last_name.end(), last_name.begin(), ::tolower);
Composer& last_name = myDB.AddComposer(in_first_name, in_last_name,
in_genre, in_yob, in_fact);
cin.clear();
} break;
...
default:
cout << "Please make a valid selection" << endl;
}
} while (selection != 48);
}
I have tried inserting a while loop after cin >> in_yob; as:
while(!cin || in_yob > 1){
cin.clear();
cout << "Enter a positive enter for year of birth: ";
cin >> in_yob;
}
but the result is an infinite loop of "Enter a positive enter for year of birth: ". I know this construct for error checking works outside of a switch case so what is the reason that within a switch case i'm getting this result? Also how would you go about fixing this so that I can check for and prevent an input error? Thanks.
[To explain my self with more space and better formatting better than in a comment I post this as an answer instead as of a comment.]
When you enter input, like for example
1
the input buffer actually contains two characters, firs the digit '1' and then the newline '\n'.
When you read a single character, the input operation extracts the first character, the digit, and writes it to your variable.
If you then read another character, it will read the newline, and not whatever comes after.
There is a trick to "ignore" characters until, for example, a newline, and that is done by using the std::istream::ignore, and if you follow the link to the reference you will see a very good example on how to ignore anything up to and including the newline.
So in your case it's not enough to just call clear you need to call ignore as well in your input validation loop. And if you continue to read single characters, you need to call ignore before that as well.
You needed to clear the input stream.
#include <iostream>
#include <string>
int in_yob = 0;
int main()
{
while(std::cin.good() && in_yob < 1){
std::cin.clear();
std::cout << "Enter a positive enter for year of birth: ";
if( !(std::cin >> in_yob) ) {
std::cin.clear();
std::cin.ignore(10000,'\n');
}
}
std::cout << "YOB " << in_yob << std::endl;
}

std::cin skips white spaces

So I am trying to write a function to check whether a word is in a sentence, by looping through a char array and checking for the same string of char's. The program works as long as the Sentence doesn't have any spaces. I googled around and they are all the same suggestions;
cin.getline
But however I implement it, it either doesn't run or skips the entire input and goes straight towards the output.
How can I account for spaces?
#include <iostream>
using namespace std;
bool isPartOf(char *, char *);
int main()
{
char* Word= new char[40];
char* Sentence= new char[200];
cout << "Please enter a word: ";
cin >> Word;
cout << endl << "Please enter a sentence: ";
//After Word is input, the below input is skipped and a final output is given.
cin.getline(Sentence, 190);
cout << endl;
if (isPartOf(Word, Sentence)==true)
{
cout << endl << "It is part of it.";
}
else
{
cout << endl << "It is not part of it.";
}
}
bool isPartOf(char* a, char* b) //This is the function that does the comparison.
{
int i,j,k;
for(i = 0; b[i] != '\0'; i++)
{
j = 0;
if (a[j] == b[i])
{
k = i;
while (a[j] == b[k])
{
j++;
k++;
return 1;
if (a[j]=='\0')
{
break;
}
}
}
}
return 0;
}
And I am not allowed to use strstr for the comparison.
Ok, I'll try to explain your problem:
Let's assume this is your input:
thisisaword
this is a sentence
When you use cin and give it any input, it stops at the newline character which in my example follows character 'd' in 'thisisaword'.
Now, your getline function will read every character until it stops newline character.
Problem is, the first character getline encounters is already a newline so it stops immediately.
How is this happening?
I'll try to explain it like this:
If this is your input given to a program (note \n characters, treat it like a single character):
thisisaword\n
this is a sentence\n
What your cin function will take and leave:
\n
this is a sentence\n
Now getline sees this input and is instructed to get every character until it meets a newline character which is "\n"
\n <- Uh oh, thats the first character it encounters!
this is a sentence\n
cin reads input and leaves "\n", where getline includes "\n".
To overcome this:
\n <- we need to get rid of this so getline can work
this is a sentence\n
As said, we cannot use cin again because it will do nothing.
We can either use cin.ignore() without any parameters and let it delete first character from input or use 2x getline(first will take remaining \n, second will take the sentence with \n)
You can also avoid this kind of problem switching your cin >> Word; to a getline function.
Since this is tagged as C++ I changed Char*[] to Strings for this example:
string Word, Sentence;
cout << "Please enter a word: "; cin >> Word;
cout << endl << Word;
cin.ignore();
cout << "\nPlease enter a sentence: "; getline(cin, Sentence);
cout << endl << Sentence;
OR
string Word, Sentence;
cout << "Please enter a word: "; getline(cin, Word);
cout << endl << Word;
cout << "\nPlease enter a sentence: "; getline(cin, Sentence);
cout << endl << Sentence;
How about using this:
std::cin >> std::noskipws >> a >> b >> c;
cin by default utilizes something like this:
std::cin >> std::skipws >> a >> b >> c;
And you can combine flags:
std::cin >> std::skipws >> a >> std::noskipws >> b;
Tell me if it works for you : )
By default operator>> skips whitespaces. You can modify that behavior.
is.unsetf(ios_base::skipws)
will cause is's >> operator to treat whitespace characters as ordinary characters.

getline() function reading in whitespace before input is entered

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.

Counting characters in a string

My code runs and works well the first time around, but I am having looping problems:
My code isn't counting characters that are in words
The second time around when you press "yes," it ends up printing everything out. I must have a loop in the wrong spot, but I can't find it for the life of me.
#include <string>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;
int main()
{
char character;
string sentence;
char answer;
int cCount;
while(1) {
cout << "Enter a character to count the number of times it is in a sentence: ";
cin >> character;
cout << "Enter a sentence and to search for a specified character: ";
cin >> sentence;
if(character == '\n' || sentence.empty())
{
cout << "Please enter a valid answer:\n";
break;
}
else {
cCount = count(sentence.begin(), sentence.end(), character);
cout << "Your sentence had" << " " << cCount << " " << character << " " << "character(s)" << '\n';
}
cout << "Do you wish to enter another sentence (y/n)?: \n";
cin >> answer;
if (answer == 'n'){
break;
}
}
return 0;
}
By just reading your code, it looks fine, except where you get the sentence. Using cin, it will only read until it sees a newline or a space, so if you're entering a sentence, it will read every word as a different input.
Try getline(cin, sentence) and see if that fixes the problem.
Edit: Forgot to add in: use cin.ignore() after the getline. cin reads up to, and including the line break (or space) while getline only reads up to the line break, so the line break is still in the buffer.
use
cin.ignore(); //dont forget to use cin.ignore() as it will clear all previous cin
getline(cin, sentence, '\n'); //take the sentence upto \n i.e entered is pressed
You don't have the loops wrong. What's wrong is that you are assuming that
cin >> sentence;
does something different from what it really does.
If you want to read a line of text, then do this
getline(cin, sentnence);
Your code reads a single word only.
use cin it will end with a newline or a space
eg:
when you input hello world it will get hello
and you can try
getline
it wiil end with a newline
This is working, try this.
#include <string>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;
int main()
{
char character;
string sentence;
char answer;
int cCount;
while(1) {
cout << "Enter a character to count the number of times it is in a sentence: ";
cin >> character;
cout << "Enter a sentence and to search for a specified character: ";
fflush(stdin);
getline(cin, sentence, '\n');
if(character == '\n' || sentence.empty())
{
cout << "Please enter a valid answer:\n";
break;
}
else {
cCount = count(sentence.begin(), sentence.end(), character);
cout << "Your sentence had" << " " << cCount << " " << character << " " << "character(s)" << '\n';
}
cout << "Do you wish to enter another sentence (y/n)?: \n";
cin >> answer;
if (answer == 'n'){
break;
}
}
return 0;
}
after you enter first input and enter that enter is considered as input in sentence
So, you need to flush that and after that you can scan that sentence.
Try:
cCount = count(sentence.c_str(), sentence.c_str()+sentence.length(), character);

Can't get char from cin.get()

I'm working through some beginner exercises on c++, and this has me stumped. I can enter a number, but I don't get the option to enter a character afterwards, and it skips to the final line.
I know I can use cin >> symbol, but i would like to know why this isn't working.
#include<iostream>
using namespace std;
int main() {
cout << "Enter a number:\n";
int number;
cin >> number;
char symbol;
cout << "Enter a letter:\n";
cin.get(symbol);
cout << number << " " << symbol << endl;
return 0;
}
You should remove '\n' from stream, remained after entering the number:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Without it you will read newline character. You could check that with:
std::cout << (symbol == '\n') << std::endl;
\n will remain in the buffer after the first cin. You can solve this problem by adding an empty cin.get() between two consecutive reads.
cin.get(string1,maxsize);
cin.get();
cin.get(string2,maxsize);
Or you can use fflush:
cin.get(string1,maxsize);
fflush(stdin);
cin.get(string2,maxsize);