C++ Ignoring CTRL D from user - c++

In my program, I am trying to check the user's input. I want him to press a given character. But my code doesn't ignore pressing CTRL+D, it becomes an infinite loop.
char ch;
cin >> ch;
while(ch != 'c' && ch != 'C'){
if (cin.eof()){
cin.clear();
}
cin >> ch;
}
Is there a way to fix this?
When I do this:
char ch;
cin >> ch;
while(ch != 'c' && ch != 'C'){
if (cin.eof()){
std::clearerr(stdin);
}
if (cin.eof()){
std::clearerr(stdin);
}
cin >> ch;
}
The second if is still true.
I am trying to do something like Press any key. I can"t seem to figure it out.

Related

while Infinite loop in function

bool isDigital(char c) { return ('0' <= c && c <= '9'); }
void DigitalToken( char digitToken[50], char ch ) {
digitToken[0] = ch;
char input = '\0';
cin >> input;
int i = 0;
while ( ( input != ' ' ) && ( input != '\t' ) && ( input != '\n' ) ) { // got a infinite loop
i++;
digitToken[i] = input;
cin >> input;
} // while ( input != ' ' && input != '\t' && input != '\n' )
} // DigitalToken()
int main() {
char ch = '\0';
while ( cin >> ch ) {
if ( isDigital(ch) ) {
char* digitToken = new char[50]();
DigitalToken(digitToken, ch);
cout << digitToken;
delete[] digitToken;
} // else if
} // while
} // main()
I don't understand why I got a infinite loop in DitgitalToken function.
When I input 123, it should be output 123.
I watched it for a long time, but I still don’t know why and how to fix it.
Instead of cin >> input; use input = cin.get();.
You have to be careful while using cin with characters or strings. It treats spaces, tabs, newlines as end of the input and hence do not treat them as input themselves.
Your program blocks in the while loop on cin >> input; after it read "123". As #Arty suggested use cin.get() instead as whitespace is stripped by default. You can also use cin >> noskipws; prior to executing cin >> input;. See skipws.

Using the newline character to break a loop in c++

I'm looking for a way to break a for loop using enter in the visual studio console.
do {
std::cin >> userInput;
if (userInput == '\n')
break;
lineStorage[lineLength] = userInput;
lineLength++;
} while(true);
This is what I have so far, but the newline character won't work for what I need it to. Any suggestions or insight would help.
P.S. I cannot use a sentinel value other than the newline character resulting from the enter button.
P.S. More context:
char lineStorage[80] = { 'a' };
char userInput = ' ';
const char lineEnd = '\n';
int lineLength = 0;
std::cout << "Enter a line:";
do {
std::cin >> userInput;
if (userInput == '\n')
break;
lineStorage[lineLength] = userInput;
lineLength++;
} while (true);
Reading with >> by default skips whitespace, and a newline is whitespace. I suggest using getline() instead:
for(int i = 0; i < 80; i++) {
if (!getline(std::cin, userInput) || userInput.empty())
break;
lineStorage[lineLength] = userInput;
lineLength++;
}
If your lineStorage is really supposed to store individual words, you can split userInput on spaces before storing the words.
Edit: now that you've shown that userInput is a single character, I think you should just use std::cin.get(userInput) to read one character at a time. That will let you get the newlines in the style of your original code.
I like the other answer better, but something like this should also work:
do {
cin.get(userInput);
if (userInput == 10) {
break;
} else {
lineStorage[lineLength] = userInput;
lineLength++;
}
} while (true);
more clear will be
#include <stdio.h>
#include <stddef.h>
int main(int argc , char *argv[])
{
char t[70]={0},x;
while(1)
{
scanf("%[^ ^\n]%c",t ,&x);
if(x == '\n') break;
}
}

First char omitted by simple programm

The task is to cin>>...., take only letters, change upper case letters to lower case and rewrite line with only lower case letters. I cannot figure out why my code is ignoring the first letter entered.
#include <iostream>
#include <cctype>
using namespace std;
int main()
{
char ch;
cin >> ch;
while (ch != '#'){
if (cin.get(ch))
{
if (isalpha(ch)){
if (isupper(ch)){
cout <<(char)tolower(ch);
}
else
cout << ch;
}
if (ch == '\n')
cout << "\nNie zakonczyles ciagu znakiem #" << endl;
}
else{
cin.clear();
}
}
}
Because the loop uses cin.get(ch) to get the character to print, but the first character is actually read with cin >> ch; and then the result is discarded.
You might want to get rid of the cin>>ch; instruction and initialize ch to a value different from '#', or transform the loop into a do-while loop, similar to this:
char ch;
do
{
if (cin.get(ch))
{
/* Do what is needed */
}
}
while (ch != '#')
cin >> ch; <- read first letter
while (ch != '#'){
if (cin.get(ch)) <- read next letter which tosses out the first letter
To fix this set ch to some value and then get rid of cin >> ch;
Because just after cin >> ch; you're doing cin.get(ch).

Accepting only numbers in the user input c++

Right now I am using this function to get the user input.
int getOnlyNumber(int num)
{
while (!(cin >> num)) {
// Reset the input:
cin.clear();
// Get rid of the bad input before return was pressed:
while (cin.get() != '\n')
{
continue;
}
// Ask user to try again:
cout << "Please enter a number: ";
}
return num;
}
This seems to only catch bad input if the letter is entered first. If a number is entered first, the program accepts it. Ex. it will accept 1e but will catch e1.
This is being used like this:
displayChoice = getOnlyNumber(displayChoice);
Where displayChoice is an int.
What do i need to change to catch 1e as a input or any other input that starts with a number but has strings?
If you give it a partial number then, by default, it does the best it can and gives you the bits it did manage to understand.
If you want to see if there was an error during the conversion then you have to check cin.fail().
while (!(cin >> num) || cin.get()!='\n') {
...
You can use std::all_of to test if an entire string is a number:
std::string str;
auto is_digit_check = [] (unsigned char c) { return std::isdigit(c); };
while (!(std::cin >> str) ||
!std::all_of(str.begin(), str.end(), is_digit_check))
{
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
return std::stoi(str);

getline won't let me type, c++

I try to get the name of a game the users chooses and store it in a vector.
I use getline so the user can use a space.
When I try to type a new game to add it won't let me.
It automaticly displays me games library.
Please tell me what I do wrong.
Problem is at
if(action == "add")
Here's my code:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <ctime>
#include <cstdlib>
using namespace std;
int main()
{
vector<string>::const_iterator myIterator;
vector<string>::const_iterator iter;
vector<string> games;
games.push_back("Crysis 2");
games.push_back("GodOfWar 3");
games.push_back("FIFA 12");
cout <<"Welcome to your Games Library.\n";
cout <<"\nThese are your games:\n";
for (iter = games.begin(); iter != games.end(); ++iter)
{
cout <<*iter <<endl;
}
//the loop!
string action;
string newGame;
cout <<"\n-Type 'exit' if you want to quit.\n-Type 'add' if you want to add a game.\n-Type 'delete' if you want to delete a game.\n-Type 'find' if you want to search a game.\n-Type 'game' if you don't know what game to play.\n-Type 'show' if you want to view your library.";
while (action != "exit")
{
cout <<"\n\nWhat do you want to do: ";
cin >> action;
//problem is here
if (action == "add")
{
cout <<"\nType the name of the game you want to add: ";
getline (cin, newGame);
games.push_back(newGame);
for (iter = games.begin(); iter != games.end(); ++iter)
{
cout <<*iter <<endl;
}
continue;
}
else if (action == "show")
{
cout <<"\nThese are your games:\n";
for (iter = games.begin(); iter != games.end(); ++iter)
{
cout <<*iter <<endl;
}
}
else if (action == "delete")
{
cout <<"Type the name of the game you want to delete: ";
cin >> newGame;
getline (cin, newGame);
iter = find(games.begin(), games.end(), newGame);
if(iter != games.end())
{
games.erase(iter);
cout <<"\nGame deleted!";
}
else
{
cout<<"\nGame not found.";
}
continue;
}
else if (action == "find")
{
cout <<"Which game you want to look for in your library: ";
cin >> newGame;
getline (cin, newGame);
iter = find(games.begin(), games.end(), newGame);
if (iter != games.end())
{
cout << "Game found.\n";
}
else
{
cout << "Game not found.\n";
}
continue;
}
else if (action == "game")
{
srand(static_cast<unsigned int>(time(0)));
random_shuffle(games.begin(), games.end());
cout << "\nWhy don't you play " << games[0];
continue;
}
else if (action == "quit")
{
cout <<"\nRemember to have fun while gaming!!\n";
break;
}
else
{
cout <<"\nCommand not found";
}
}
return 0;
}
I don't get what you exactly wrote, but:
getline will fetch the whole line in its second parameter in your case newGame
when you call cin >> newGame; above the getline, you frst use the istream operator >> of string. It reads until the first separator. This in your case is the space between Tomb and Raider
Afterwords you overwrite the value read with cin >> newGame; using the getline. Until the getline the value was Tomb, afterwords it becomes Raider
Just remove the cin:
cin >> newGame;
getline (cin, newGame);
->
getline (cin, newGame);
EDIT Now as you posted all your code I am sure your case is exactly what I thought of. In the line cin >> action; you prompt the user to select an action. He enters it and hits enter so he can make your program active once more. However, the cin >> will read the value, but not clear the enter the user pressed. Thus the first getline you invoke will just read this enter and nothing else. If you do:
cin >> newGame;
getline (cin, newGame);
->
cin.get();
getline (cin, newGame);
This will work. I tried it. Basically the first cin.get(); clears the enter and the getline prompts the user for input.
EDIT2 Adding one more improvement on the lay the trailing new lines are handled. This is maybe the most correct way to handle them, but I intentionally did not provide this solution trying not to confuse the OP with complex code:
if (cin.peek() == '\n' || cin.peek() == '\r') {
cin.get();
}
getline (cin, newGame);
Mixing
cin >> value1;
and
getline(cin, value2);
is inviting trouble. The problem is that getline reads until the next '\n' (and consumes it), while >> reads until the next white-space (and does not consume it).
This means that when you read value1 via >>, the new-line character remains in the stream, then you try to read a whole line and read "nothing" (the getline will consume the new-line character that is the immediate input from the stream).
Suggestions of doubling the getline will work, but only until you read via getline in another branch, when it will break, because that getline consumes the new-line, contrary to >>, which does not.
I suggest you handle all your input via getline, then tokenize the read string, if further processing is needed. This way ou ensure that the new-line handling is consistent and also that spaces are read correctly.
Could you please try this:
cout <<"Type the name of the game you want to add: ";
instead of your this code:
cout <<"\nType the name of the game you want to add: ";
I am not sure whether it works or not. but please give a try.
The problem maybe because of a stray '\n'. getline as the name suggests gets the values of the complete line. So how does your compiler know when you have finished. It uses the character \n. If it reads a left over \n it will assume that the line has ended, so if u remove it i think it should work.So just find out the line before the getline which may have left a stray \n.