场景:
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; }