如何使用 getc() 在 D 中获取单个按键?
How to get single keypress in D with getc()?
我需要在控制台中获取用户输入 (y/n) 按键。
我该怎么做?我知道我可以使用 readln,但还有其他方法吗?我正在尝试使用 getc()
import std.stdio;
import std.string;
import std.stream;
void main()
{
while (getc() != 'y')
{
writeln("try again");
}
}
但我收到错误消息:
source\app.d(6): Error: function core.stdc.stdio.getc (shared(_iobuf)* stream) is not callable using argument types (File)
下一次尝试:
char [] checkYesNo() @property
{
char [] key;
while(readln(key) != 'y')
{
}
return key;
}
此代码编译通过,但在执行时因奇怪错误而失败 "Error executing command run"
错误是因为 phobos 与运行时冲突。
std.stdio
公开导入 core.stdc.stdio
,它们都定义了 stdin
,但类型不同。 getc()
实际上只是调用 fgetc( stdin )
,因此当运行时尝试调用 getc()
时,它会传入 std.stdio
中的 stdin
而不是 [=13] 中的正确的 stdin
=], 导致错误.
解决冲突的最佳方法是将 core.stdc.stdio
别名设为其他名称,然后使用完全限定名称。
import std.stdio;
void main()
{
while (getc() != 'y')
{
writeln("try again");
}
}
auto getc()
{
import stdc = core.stdc.stdio;
return stdc.getc( stdc.stdin );
}
但请注意 getc()
在内部使用缓冲区,并且不会 return 直到用户按下回车键,此时它从缓冲区读取第一个字符并且 returns that, and will continue to read the next char from the buffer for subsequent calls until it reads the end。因此在终端 window 中输入 nnn<enter>
会导致 try again
被打印 3 次。如果你想要一个 return 不需要回车键的单个字符的方法,你需要寻找一个库解决方案,C 或 D 中都没有标准函数。
如果您不关心 cross-platform 解决方案,可以使用 Windows-specific header 定义不使用缓冲区的 getch()
函数和 returns 在每次击键时,而不是在输入时。只需将其添加到您的代码中,并将对 getc()
的调用替换为对 getch()
.
的调用
extern( C ) int getch();
我的 terminal.d
有一个可以单按的图书馆
https://github.com/adamdruppe/arsd/blob/master/terminal.d
它看起来比实际更复杂。这是获取单个密钥的示例:
import terminal;
void main() {
auto terminal = Terminal(ConsoleOutputType.linear);
auto input = RealTimeConsoleInput(&terminal, ConsoleInputFlags.raw);
terminal.writeln("Press any key to exit");
auto ch = input.getch();
terminal.writeln("Bye!");
}
要构建,请将 terminal.d 放入您的文件夹,然后将它们一起编译:dmd yourfile.d terminal.d
.
首先,您构建一个终端。这两种类型是线性的或蜂窝状的。 Linear 一次输出一行,cellular 在控制台中变为 "full screen"。
然后,您根据该终端创建一个输入结构。 ConsoleInputFlags
说的是你想要的:你想要回声吗?鼠标输入?等。raw
是最简单的一个:它会向您发送纯键盘输入,因为它们发生的情况相对较少。
然后您可以写入终端并从输入中获取字符。 input.getch()
行获取单个字符,当某些内容可用时立即返回而无需缓冲。 input
上可用的其他功能包括 kbhit
,其中 returns 如果按下某个键则输入可用,则为 true,否则为 false - 对实时游戏有用,正在检查一个计时器,或 nextEvent
,它提供完整的输入支持,包括鼠标事件。 terminal.d 源代码中的演示显示了完全支持的内容:
https://github.com/adamdruppe/arsd/blob/master/terminal.d#L2265
terminal
本身的另一个有用的便利功能是 getline
,它一次抓取整行,但也允许用户编辑它并提供历史记录和自动完成。 terminal
还提供了一个名为 color
的功能来进行彩色输出,而 moveTo
在蜂窝模式下很有用,可以在屏幕上移动光标。如果您有兴趣,请浏览代码以了解更多信息。
怎么样:
import std.stdio;
void main(){
writefln("Enter something: ");
char entered;
do{
readf(" %c\n", &entered);
writefln("Entered: %s", entered);
}while(entered != 'y');
}
重要的一点是“%c\n”。
%c 告诉 readf 匹配字符而不是字符串。
我需要在控制台中获取用户输入 (y/n) 按键。
我该怎么做?我知道我可以使用 readln,但还有其他方法吗?我正在尝试使用 getc()
import std.stdio;
import std.string;
import std.stream;
void main()
{
while (getc() != 'y')
{
writeln("try again");
}
}
但我收到错误消息:
source\app.d(6): Error: function core.stdc.stdio.getc (shared(_iobuf)* stream) is not callable using argument types (File)
下一次尝试:
char [] checkYesNo() @property
{
char [] key;
while(readln(key) != 'y')
{
}
return key;
}
此代码编译通过,但在执行时因奇怪错误而失败 "Error executing command run"
错误是因为 phobos 与运行时冲突。
std.stdio
公开导入 core.stdc.stdio
,它们都定义了 stdin
,但类型不同。 getc()
实际上只是调用 fgetc( stdin )
,因此当运行时尝试调用 getc()
时,它会传入 std.stdio
中的 stdin
而不是 [=13] 中的正确的 stdin
=], 导致错误.
解决冲突的最佳方法是将 core.stdc.stdio
别名设为其他名称,然后使用完全限定名称。
import std.stdio;
void main()
{
while (getc() != 'y')
{
writeln("try again");
}
}
auto getc()
{
import stdc = core.stdc.stdio;
return stdc.getc( stdc.stdin );
}
但请注意 getc()
在内部使用缓冲区,并且不会 return 直到用户按下回车键,此时它从缓冲区读取第一个字符并且 returns that, and will continue to read the next char from the buffer for subsequent calls until it reads the end。因此在终端 window 中输入 nnn<enter>
会导致 try again
被打印 3 次。如果你想要一个 return 不需要回车键的单个字符的方法,你需要寻找一个库解决方案,C 或 D 中都没有标准函数。
如果您不关心 cross-platform 解决方案,可以使用 Windows-specific header 定义不使用缓冲区的 getch()
函数和 returns 在每次击键时,而不是在输入时。只需将其添加到您的代码中,并将对 getc()
的调用替换为对 getch()
.
extern( C ) int getch();
我的 terminal.d
有一个可以单按的图书馆https://github.com/adamdruppe/arsd/blob/master/terminal.d
它看起来比实际更复杂。这是获取单个密钥的示例:
import terminal;
void main() {
auto terminal = Terminal(ConsoleOutputType.linear);
auto input = RealTimeConsoleInput(&terminal, ConsoleInputFlags.raw);
terminal.writeln("Press any key to exit");
auto ch = input.getch();
terminal.writeln("Bye!");
}
要构建,请将 terminal.d 放入您的文件夹,然后将它们一起编译:dmd yourfile.d terminal.d
.
首先,您构建一个终端。这两种类型是线性的或蜂窝状的。 Linear 一次输出一行,cellular 在控制台中变为 "full screen"。
然后,您根据该终端创建一个输入结构。 ConsoleInputFlags
说的是你想要的:你想要回声吗?鼠标输入?等。raw
是最简单的一个:它会向您发送纯键盘输入,因为它们发生的情况相对较少。
然后您可以写入终端并从输入中获取字符。 input.getch()
行获取单个字符,当某些内容可用时立即返回而无需缓冲。 input
上可用的其他功能包括 kbhit
,其中 returns 如果按下某个键则输入可用,则为 true,否则为 false - 对实时游戏有用,正在检查一个计时器,或 nextEvent
,它提供完整的输入支持,包括鼠标事件。 terminal.d 源代码中的演示显示了完全支持的内容:
https://github.com/adamdruppe/arsd/blob/master/terminal.d#L2265
terminal
本身的另一个有用的便利功能是 getline
,它一次抓取整行,但也允许用户编辑它并提供历史记录和自动完成。 terminal
还提供了一个名为 color
的功能来进行彩色输出,而 moveTo
在蜂窝模式下很有用,可以在屏幕上移动光标。如果您有兴趣,请浏览代码以了解更多信息。
怎么样:
import std.stdio;
void main(){
writefln("Enter something: ");
char entered;
do{
readf(" %c\n", &entered);
writefln("Entered: %s", entered);
}while(entered != 'y');
}
重要的一点是“%c\n”。 %c 告诉 readf 匹配字符而不是字符串。