I have a loop running that displays data read from a serial port on a console screen, the same screen lists some options for the user, such as the option to enter a file name that data would be logged to, or exit. The user presses the required key to enter the desired option.
After the key press and the option function entered any key presses can be ignored/discarded but I am not able to find a way to discard the key presses/ clear the cin buffer resulting in the key press being shown on the console.
Is there any way to clear the cin buffer without the user having to take any action? Or possibly some better way to provide the same functionality?
A stripped down version of code here: (this should display the local time while giving the user the option to enter a "file name" or exit, no serial port stuff included)
#include <iostream>
#include <limits>
#include <chrono>
#include <windows.h>
using namespace std;
// global variables
char SavedFileName[20];
HANDLE hConsole;
CONSOLE_SCREEN_BUFFER_INFO csbi;
// functions
void GetTime(void){
char buffer [20];
time_t now = time(NULL);
strftime(buffer , 20, "%H:%M:%S %d/%m/%Y", localtime(&now));
cout << "local time: " << buffer << endl;
}
bool is1keypressed(void){
if(GetAsyncKeyState(49) & 0x8000){
return true;
}
return false;
}
bool is9keypressed(void){
if(GetAsyncKeyState(57) & 0x8000){
return true;
}
return false;
}
int ClearConsole(void){
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SMALL_RECT scrollRect;
COORD scrollTarget;
CHAR_INFO fill;
// Get the number of character cells in the current buffer.
if (!GetConsoleScreenBufferInfo(hConsole, &csbi))
return 0;
// Scroll the rectangle of the entire buffer.
scrollRect.Left = 0;
scrollRect.Top = 0;
scrollRect.Right = csbi.dwSize.X;
scrollRect.Bottom = csbi.dwSize.Y;
// Scroll it upwards off the top of the buffer with a magnitude of the entire height.
scrollTarget.X = 0;
scrollTarget.Y = (SHORT)(0 - csbi.dwSize.Y);
// Fill with empty spaces with the buffer's default text attribute.
fill.Char.UnicodeChar = TEXT(' ');
fill.Attributes = csbi.wAttributes;
// Do the scroll
ScrollConsoleScreenBuffer(hConsole, &scrollRect, NULL, scrollTarget, &fill);
return 0;
}
int main(){
bool exit = false;
// clear the console
ClearConsole();
// main loop
while(!exit){
// Move the cursor to the top left corner too.
csbi.dwCursorPosition.X = 0;
csbi.dwCursorPosition.Y = 0;
SetConsoleCursorPosition(hConsole, csbi.dwCursorPosition);
// prints the local time each on iteration of loop
GetTime();
// user options
cout << "\npress (1) enter file name - saved file name is: " << SavedFileName;
cout << "\npress (9) to exit." << endl;
// test user options
if(is1keypressed()){
cout << "option 1 - press ENTER to proceed " << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
bool validentry = false;
while(!validentry){
cout << "Enter a file name, max 19 characters: ";
cin.getline(SavedFileName, 20, '\n');
if(cin.fail()){
validentry = false;
cout << endl << "File name is too large, enter 19 characters or less. " << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}else
validentry = true;
}
ClearConsole();
}
exit = is9keypressed();
}
cout << "\n end program" << endl;
return 0;
}
I have experimented with cin.ignore, this leaves the user to press Enter to proceed. Without cin.ignore the user has to delete the "option" characters themselves.