1
votes

Hello [and sorry for my bad english] ,

I have programmed a little network card game (console application) with winsock in C++. Basically the program executes the following way:

1) Open Socket and wait for a peer to connect
2) If connected -> start game
3) If its your turn -> decide which action should be taken next and type it in
3.1) If its not your turn -> wait for your peers decision

While the users are waiting it´s possible for them to type some stuff into the console (it actually doesnt get printed while typing). If the user has its turn there are three possible outcomes:

1) The user inputs only valid data -> program runs fine
2) The user inputs trash while waiting but doesnt press enter (no \n)
3) The user inputs trash while waiting and does press enter (\n)

In case 2) and 3) I have a big problem: Because there seems to be some input left in the input buffer, my call to std::getline (to get the user input) takes the trash which the user inputs previously.

Example: I start the program and wait for another user to join my game. While waiting I input 'abc' into the console and press Enter. Another user joins the game. After some setup work the program should take my input so that I can decide which action to do next. But this doesnt happen. Firstly 'abc' gets printed on the screen, secondly the program doesnt wait for my input because it uses the 'abc' as the input for the std::getline call.

Here is a code sample to reproduce my "problem":

int main()
{
    std::string str;
    std::cout << "Before sleep";
    std::this_thread::sleep_for(5s);

    std::cin.ignore(std::numeric_limits<std::streamsize>::max());
    std::cin.clear();

   std::getline(std::cin, str);
}

I simulated the "waiting" with this_thread::sleep_for(5s). While waiting you can input trash and based on your input it prints it after 5s and waits for more input or ends the program if you dont use std::cin.ignore and std::cin.clear.

std::ignore() and std::clear dont seem to work the way I thought they would work (clearing the input buffer and resetting the std::cin status flags)

My questions:

1) How can I empty the input buffer before getting user input?

2) Why does the console print my input ?

1
1) The shown code appears to be fully flushing the input buffer already. 2) Because that's how terminal consoles work. It's out of your program's control. Your question is unclear.Sam Varshavchik
Thanks for your answer. If the user inputs invalid data before std::getline is called (in my example it is when the thread sleeps) the input buffer will contain this invalid data. The invalid data will be used for the std::getline call. If I use std::cin.ignore() and std::cin.clear() the console waits for additional input and I have to end it with CTRL+Z and Enter. If i dont use std::ignore() and std::clear() the variable str will contain the last line invalid data and terminates the program. How can I clear the input buffer before the user should actually input real data?Byte

1 Answers

0
votes

Using “std::cin.ignore(std::numeric_limits::max(),'\n');” after the “cin” statement discards everything in the input stream including the newline.

Here is my code:

int main()
{
    std::string str;
    std::cout << "Before sleep\n";

    ……//Simulate wait time

    std::string str1;
    std::cin >> str1;
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');  
    std::getline(std::cin, str);
    std::cout << str;
}

I enter "ASD" during the waiting time and print "ASD" after the waiting time has elapsed. And then I continue to input characters, only output characters that are entered later.

EDIT: If you want to achieve that the trash was entered during the waiting time does not appear on the console? If so, I suggest you could try to run the code:

#include <iostream>
#include <chrono>
#include <thread>
#include<string>
#include <limits>
#include<stdio.h>
#include<windows.h>
#include <WinBase.h>

using namespace std::chrono_literals;

int main()
{
    std::string str;
    std::cout << "Before sleep\n";
    std::this_thread::sleep_for(5s);
    std::getline(std::cin, str);



    int i;
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    GetConsoleScreenBufferInfo(hConsole, &csbi);
    COORD pos = { 0,1 };
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
    for (i = 1; i <= 10; i++)
        std::cout << ' ';
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);


    std::cin.get();
    std::cin.clear();  // Reset all state values in the stream to valid values
    std::cin.sync();   //Empty stream

    std::getline(std::cin, str);
}