Variante de la réponse de ssinfod pour Linux qui me semble un peu plus propre à mes goûts, implémentée pour wcout
et wchar_t
, et efface les caractères invalides sans bugs.
#include
//Pour kbhit() sur Linux. Pour Windows, utilisez conio.h.
#ifdef __unix__
#include //Pour FIONREAD.
#include
//À appeler au démarrage du programme pour configurer kbhit.
void initTerminalInput()
{
//Désactive le buffer interne.
std::wcout << std::unitbuf;
//Désactive le buffering en ligne.
struct termios term;
tcgetattr(0, &term);
term.c_lflag &= ~ICANON;
tcsetattr(0, TCSANOW, &term);
setbuf(stdin, NULL);
}
//Retourne 0 s'il n'y a pas de caractère d'entrée à lire.
int kbhit()
{
static int nbbytes;
ioctl(0, FIONREAD, &nbbytes);
return nbbytes;
}
#endif
//Attend et récupère un seul caractère validé, appelant une fonction de validation sur chaque caractère saisi et
//effaçant tout caractère invalide (lorsque la fonction de validation renvoie false).
static wchar_t getWChar(std::function validationFunction)
{
static wchar_t inputWChar;
do
{
//Attendre qu'un caractère d'entrée soit saisi.
while (!kbhit())
{
}
inputWChar = getwchar();
//Valider le caractère d'entrée.
if (validationFunction(inputWChar))
{
//Valide.
break;
}
else
{
//Effacer le caractère invalide.
std::wcout << L"\b \b";
}
} while (true);
return inputWChar;
}
Dans l'exemple ci-dessous, je voulais que l'utilisateur saisisse soit 1, 2, ou 3. Tous les autres caractères saisis ne seront pas affichés, et le programme attendra l'appui sur l'un des caractères valides:
int main()
{
#ifdef __unix__
initTerminalInput();
#endif
getWChar([] (wchar_t inputWChar)
{
return (inputWChar >= L'1' && inputWChar <= L'3');
});
return 0;
}
1 votes
@adam - Pouvez-vous clarifier : Voulez-vous une fonction qui retournera immédiatement si aucun caractère n'est disponible, ou une qui attendra toujours une seule pression de touche?
3 votes
@Roddy - Je veux une fonction qui attendra toujours une seule frappe de touche.