场景:
1. 在做多线程单元测试时难免需要在控制台打印数据,如果是实时输出的话,通过getc方式还需要输入一个回车键,不能及时响应,还有就是屏幕刷屏时可能都看不清自己敲了什么字母. 关键代码PressAnyKey是参考cplusplus的。
参考: http://www.cplusplus.com/forum/articles/7312/
Linux,Unix,MacOSX
#include <stdio.h>
#include <assert.h>
#include <string>
#include "gtest/gtest.h"
#include "gtest/internal/gtest-filepath.h"
#include "gtest/internal/gtest-port.h"
#include <pthread.h>
#include <unistd.h>
#include <termios.h>
//http://www.cplusplus.com/forum/articles/7312/
int PressAnyKey( const char* prompt )
{
#define MAGIC_MAX_CHARS 18
struct termios initial_settings;
struct termios settings;
unsigned char keycodes[ MAGIC_MAX_CHARS ];
int count;
tcgetattr( STDIN_FILENO, &initial_settings );
settings = initial_settings;
/* Set the console mode to no-echo, raw input. */
/* The exact meaning of all this jazz will be discussed later. */
settings.c_cc[ VTIME ] = 1;
settings.c_cc[ VMIN ] = MAGIC_MAX_CHARS;
settings.c_iflag &= ~(IXOFF);
settings.c_lflag &= ~(ECHO | ICANON);
tcsetattr( STDIN_FILENO, TCSANOW, &settings );
printf( "%s", prompt ? prompt : "Press a key to continue..." );
int fo = fileno(stdin);
count = read( fo, (void*)keycodes, MAGIC_MAX_CHARS );
tcsetattr( STDIN_FILENO, TCSANOW, &initial_settings );
return (count == 1)
? keycodes[ 0 ]
: -(int)(keycodes[ count -1 ]);
}
void * StartPthread(void * arg)
{
static int i = 0;
while(true)
{
GTEST_LOG_(INFO) << "StartPthread: " << i++ ;
sleep(2);
}
}
int main(int argc, char const *argv[])
{
#if 1
pthread_t t1;
pthread_create(&t1, NULL, StartPthread, NULL);
pthread_detach(t1);
while(true)
{
int c = PressAnyKey("Press any key to continue.");
GTEST_LOG_(INFO) << "c: " << c ;
if(c == 'q')
{
break;
}
}
#endif
return 0;
}
Windows:
/* ---------------------------------------------------------------------------
* PressAnyKey()
* ---------------------------------------------------------------------------
* Copyright 2008 Michael Thomas Greer
* http://www.boost.org/LICENSE_1_0.txt
*
* function
* Optionally print a message and and wait for the user to press (and
* release) a single key.
*
* arguments
* The message to print. If NULL, uses a default message. Specify the empty
* string "" to not print anything.
*
* returns
* The virtual keycode for the key that was pressed.
*
* Windows #defines virtual keycode values like
* VK_UP
* VK_DOWN
* VK_RIGHT
* VK_LEFT
* which you can use to identify special keys.
*
* Letter keys are simply the upper-case ASCII value for that letter.
*/
#include <windows.h>
#include <iostream>
using namespace std;
int PressAnyKey( const char *prompt )
{
DWORD mode;
HANDLE hstdin;
INPUT_RECORD inrec;
DWORD count;
char default_prompt[] = "Press a key to continue...";
/* Set the console mode to no-echo, raw input, */
/* and no window or mouse events. */
hstdin = GetStdHandle( STD_INPUT_HANDLE );
if (hstdin == INVALID_HANDLE_VALUE
|| !GetConsoleMode( hstdin, &mode )
|| !SetConsoleMode( hstdin, 0 ))
return 0;
if (!prompt) prompt = default_prompt;
/* Instruct the user */
WriteConsole(
GetStdHandle( STD_OUTPUT_HANDLE ),
prompt,
lstrlen( prompt ),
&count,
NULL
);
FlushConsoleInputBuffer( hstdin );
/* Get a single key RELEASE */
do ReadConsoleInput( hstdin, &inrec, 1, &count );
while ((inrec.EventType != KEY_EVENT) || inrec.Event.KeyEvent.bKeyDown);
/* Restore the original console mode */
SetConsoleMode( hstdin, mode );
return inrec.Event.KeyEvent.wVirtualKeyCode;
}
int main(int argc, char const *argv[])
{
int keyCode = PressAnyKey(NULL);
cout << "keyCode: " << (char)keyCode << endl;
return 0;
}