我永遠不會記得我是如何做到這一點的,因爲它對我來說很少出現。但在C或C++中,從標準輸入中讀取字符而不等待換行(按Enter)的最佳方式是什麼。從標準輸入捕獲字符而不等待輸入被按下
理想情況下,它不會將輸入字符回顯到屏幕。我只想捕獲擊出控制檯屏幕的擊鍵。
我永遠不會記得我是如何做到這一點的,因爲它對我來說很少出現。但在C或C++中,從標準輸入中讀取字符而不等待換行(按Enter)的最佳方式是什麼。從標準輸入捕獲字符而不等待輸入被按下
理想情況下,它不會將輸入字符回顯到屏幕。我只想捕獲擊出控制檯屏幕的擊鍵。
這在純C++中是不可能移植的,因爲它太依賴於可能與stdin連接的終端(它們通常是線路緩衝)。但是,您可以使用以下庫:
_getch()
爲您提供一個角色,而無需等待輸入密鑰。我不是一個頻繁的Windows開發人員,但我看到我的同學只包括conio.h
並使用它。請參閱維基百科的conio.h。它列出了getch
,它在Visual C++中聲明爲不贊成使用。getch
函數。 (嘗試man getch
查看其聯機幫助頁)。請參閱維基百科的Curses。如果您的目標是跨平臺兼容性,我建議您使用curses。也就是說,我確定有一些函數可以用來關閉行緩衝(我相信這就是所謂的「原始模式」,而不是「熟化模式」(查看man stty
))。如果我沒有弄錯,詛咒會以便攜方式爲你處理。
請注意,現在`ncurses`是'curses`的推薦變種。 – 2016-05-07 03:04:01
如果你確實需要一個圖書館,那他們是怎麼做到的?爲了使圖書館你一定要編程它,這意味着任何人都可以編程,所以爲什麼我們不能編程我們自己需要的庫代碼?這也將使**這不可能在純粹的C + +錯誤 – NathanProgrammer 2017-01-03 09:49:00
@ kid8我不明白 – 2017-01-03 16:51:24
假設Windows,看看ReadConsoleInput函數。
C和C++採用非常抽象的I/O視圖,並且沒有標準的做你想做的方式。有標準的方法可以從標準輸入流中獲取字符,如果有任何可以獲得的字符,其他任何語言都不會定義其他字符。因此,任何答案都必須是平臺特定的,可能不僅取決於操作系統,還取決於軟件框架。
這裏有一些合理的猜測,但沒有辦法在不知道目標環境是什麼的情況下回答你的問題。
CONIO.H
您需要的功能是:
int getch();
Prototype
int _getch(void);
Description
_getch obtains a character from stdin. Input is unbuffered, and this
routine will return as soon as a character is available without
waiting for a carriage return. The character is not echoed to stdout.
_getch bypasses the normal buffering done by getchar and getc. ungetc
cannot be used with _getch.
Synonym
Function: getch
int kbhit();
Description
Checks if a keyboard key has been pressed but not yet read.
Return Value
Returns a non-zero value if a key was pressed. Otherwise, returns 0.
libconio http://sourceforge.net/projects/libconio
或
Linux下C++實現CONIO.H的 http://sourceforge.net/projects/linux-conioh
如果您使用的是Windows,你可以使用PeekConsoleInput來檢測是否有任何輸入,
HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
DWORD events;
INPUT_RECORD buffer;
PeekConsoleInput(handle, &buffer, 1, &events);
然後使用ReadConsoleInput「消費」輸入字符..
PeekConsoleInput(handle, &buffer, 1, &events);
if(events > 0)
{
ReadConsoleInput(handle, &buffer, 1, &events);
return buffer.Event.KeyEvent.wVirtualKeyCode;
}
else return 0
說實話這是來自我的一些舊代碼,所以你必須用它來擺弄一下。
雖然很酷的事情是它讀取輸入時沒有提示任何內容,所以字符根本不顯示。
以下是從提取的解決方案專家C編程:深度祕密,它應該在SVr4上工作。它使用stty和ioctl。
#include <sys/filio.h>
int kbhit()
{
int i;
ioctl(0, FIONREAD, &i);
return i; /* return a count of chars available to read */
}
main()
{
int i = 0;
intc='';
system("stty raw -echo");
printf("enter 'q' to quit \n");
for (;c!='q';i++) {
if (kbhit()) {
c=getchar();
printf("\n got %c, on iteration %d",c, i);
}
}
system("stty cooked echo");
}
我發現這在另一個論壇上,同時尋找解決同樣的問題。我從我發現的內容中修改了一下。它效果很好。我正在運行OS X,因此如果您運行的是Microsoft,則需要找到正確的system()命令切換到raw和cooked模式。
#include <iostream>
#include <stdio.h>
using namespace std;
int main() {
// Output prompt
cout << "Press any key to continue..." << endl;
// Set terminal to raw mode
system("stty raw");
// Wait for single character
char input = getchar();
// Echo input:
cout << "--" << input << "--";
// Reset terminal to normal "cooked" mode
system("stty cooked");
// And we're out of here
return 0;
}
在Linux(和其他類Unix系統),這可以在下列方式進行:
#include <unistd.h>
#include <termios.h>
char getch() {
char buf = 0;
struct termios old = {0};
if (tcgetattr(0, &old) < 0)
perror("tcsetattr()");
old.c_lflag &= ~ICANON;
old.c_lflag &= ~ECHO;
old.c_cc[VMIN] = 1;
old.c_cc[VTIME] = 0;
if (tcsetattr(0, TCSANOW, &old) < 0)
perror("tcsetattr ICANON");
if (read(0, &buf, 1) < 0)
perror ("read()");
old.c_lflag |= ICANON;
old.c_lflag |= ECHO;
if (tcsetattr(0, TCSADRAIN, &old) < 0)
perror ("tcsetattr ~ICANON");
return (buf);
}
基本上你必須關閉典型模式(和回聲模式,以抑制呼應)。
#include <conio.h>
if (kbhit() != 0) {
cout << getch() << endl;
}
這使用kbhit()
檢查是否被按下了鍵盤,並使用getch()
來獲取被按下的字符。
您可以使用SDL(Simple DirectMedia Library)輕鬆轉換,儘管我懷疑您可能不喜歡它的行爲。當我嘗試它時,我不得不讓SDL創建一個新的視頻窗口(儘管我不需要它用於我的程序),並讓此窗口「抓住」幾乎所有的鍵盤和鼠標輸入(這對我的使用來說是可以的,但可以在其他情況下令人討厭或不可行)。我懷疑它是過度的,不值得這樣做,除非完全的可移植性是必須的 - 否則嘗試其他建議的解決方案之一。
順便說一句,如果你喜歡這樣,這將分別爲你提供按鍵和發佈事件。
我一直想要一個循環來讀取我的輸入,而不按回車鍵。 這爲我工作。
#include<stdio.h>
main()
{
char ch;
system("stty raw");//seting the terminal in raw mode
while(1)
{
ch=getchar();
if(ch=='~'){ //terminate or come out of raw mode on "~" pressed
system("stty cooked");
//while(1);//you may still run the code
exit(0); //or terminate
}
printf("you pressed %c\n ",ch); //write rest code here
}
}
爲我工作在Windows上:
#include <conio.h>
char c = _getch();
我用的kbhit(),看是否有燒焦存在,然後的getchar()讀取數據。 在窗口上,您可以使用「conio.h」。在Linux上,你將不得不實現你自己的kbhit()。
見下面的代碼:
// kbhit
#include <stdio.h>
#include <sys/ioctl.h> // For FIONREAD
#include <termios.h>
#include <stdbool.h>
int kbhit(void) {
static bool initflag = false;
static const int STDIN = 0;
if (!initflag) {
// Use termios to turn off line buffering
struct termios term;
tcgetattr(STDIN, &term);
term.c_lflag &= ~ICANON;
tcsetattr(STDIN, TCSANOW, &term);
setbuf(stdin, NULL);
initflag = true;
}
int nbbytes;
ioctl(STDIN, FIONREAD, &nbbytes); // 0 is STDIN
return nbbytes;
}
// main
#include <unistd.h>
int main(int argc, char** argv) {
char c;
//setbuf(stdout, NULL); // Optional: No buffering.
//setbuf(stdin, NULL); // Optional: No buffering.
printf("Press key");
while (!kbhit()) {
printf(".");
fflush(stdout);
sleep(1);
}
c = getchar();
printf("\nChar received:%c\n", c);
printf("Done.\n");
return 0;
}
你在Windows或不呢? – hasen 2009-01-08 00:55:46
@adam - 你能否澄清一下:你是否想要一個函數,如果沒有可用的字符,它會立即返回,或者一直等待一個按鍵? – Roddy 2009-01-08 09:47:30
@Roddy - 我想要一個總是等待一個按鍵的功能。 – Adam 2009-05-28 04:52:54