有没有一种简单的、跨平台的方法来使用Phobos在D2中进行单次击键?
例如,“按任意键继续...”prompt或Brainfuck解释器。
我尝试过的所有方法都需要在传递输入之前按Enter键(例如,getchar())。
发布于 2011-03-22 05:31:36
我在这个问题上做了一些研究,我发现,虽然D1.0下的Phobos库以std.c.stdio.getch()的形式提供了您所需要的东西,但D2.0缺少这个功能。Phobos中的其他标准输入函数似乎都没有您想要的行为。
据我所知,这是因为所需的行为(即,在不需要按Enter键的情况下获得单个字符)是相当不标准的,并且必须以相对丑陋的、特定于平台的方式来实现。(在最初的形式中,函数getch存在于C的中,这是一个特定于DOS的头文件,尽管它不是标准C库的一部分,但它已经成为某种程度上的跨平台标准。)显然,Phobos运行时库的维护者决定以更干净的库的名义剥离这一特定的向后兼容功能,但代价是这一功能。
手动声明
Reportedly,您可以通过将以下内容添加到源文件中来绕过缺少的函数声明:
extern (C) int getch();但是,我发现这会产生一个链接器错误,这表明该函数已从运行时库中完全删除,而不仅仅是将其声明从std.c.stdio中删除。这当然值得一试-它可能碰巧在你的系统和编译器上工作,我真的不知道。
WindowsEdit2:这看起来在Windows端是可行的;我在Linux端失败了。在Windows下,DMD似乎首先链接到Phobos/D运行时(phobos.lib),然后是C运行时(snn.lib);然而,在Linux上,DMD链接到一个提供这两个部分的运行时库。这种差异似乎导致到未声明的函数(其中包括getch)的链接仅在Windows上有效。如果Windows是您唯一关心的平台,那么这个解决方案可能是合适的。如果您需要更多跨平台兼容性,请继续阅读。
ncurses
另一种可能是使用ncurses库。它实现了一个getch函数,这个函数肯定会做你想做的事情--前提是你愿意为这个库找到D绑定,或者只使用C接口。请注意,它需要更多的设置,而不仅仅是调用您想要的函数;this thread提供了有关此问题的更多信息。
D 1.0
现在,对于一些相当丑陋的解决方案。使用D1.0将允许您在Phobos标准库中找到所需的内容-但这显然需要使用该语言的旧版本,而且我个人并不认为标准库中缺少一个控制台IO函数可以作为使用旧版本D的理由。
我相信,在切换到D2.0的过程中,探戈也丢失了它的getch声明(在tango.stdc.stdio下),但我对探戈的了解非常有限,所以我可能错了。
你自己写吧
如果你下定决心,你可以写你自己的getch。我找不到使用Google Code Search的getch的跨平台C实现,这让我对相对简单的、大约10行左右的函数实现可以简单地适应D的可能性感到悲观。
另一方面,沃尔特·布赖特--你知道,设计了D语言--提供了这类函数here的D实现。然而,即使这样也显得有些过时,因为在当前版本的DMD2编译器下,其中一个符号cfmakeraw是未定义的。然而,它真的很接近成为一个可行的解决方案。
发布于 2011-03-22 05:40:40
在Windows上使用D2的最简单的解决方案是:
import std.stdio : writefln;
extern(C) int kbhit();
extern(C) int getch();
void main()
{
while(!kbhit())
{
// keep polling
// might use Thread.Sleep here to avoid taxing the cpu.
}
writefln("Key hit was %s.", cast(char)getch());
}它甚至可以在D1上工作,但我还没有试过。
这是一个由Walter's post修改的Linux版本
import std.stdio : writefln;
import std.c.stdio;
import std.c.linux.termios;
extern(C) void cfmakeraw(termios *termios_p);
void main()
{
termios ostate; /* saved tty state */
termios nstate; /* values for editor mode */
// Open stdin in raw mode
/* Adjust output channel */
tcgetattr(1, &ostate); /* save old state */
tcgetattr(1, &nstate); /* get base of new state */
cfmakeraw(&nstate);
tcsetattr(1, TCSADRAIN, &nstate); /* set mode */
// Read characters in raw mode
writefln("The key hit is %s", cast(char)fgetc(stdin));
// Close
tcsetattr(1, TCSADRAIN, &ostate); // return to original mode
}https://stackoverflow.com/questions/5372646
复制相似问题