【问题标题】:ANSI C No-echo keyboard inputANSI C 无回音键盘输入
【发布时间】:2009-02-17 18:01:20
【问题描述】:

我一直在谷歌搜索,但没有运气。我正在寻找一种方法来做 getc() 或 gets() 或任何不会回显到终端的方法。我看到了 kbhit() 但这似乎不是 ANSI 的一部分。理想情况下,我希望代码看起来像

char s[100];
no_echo_gets(s); /* Won't echo to screen while being typed */
printf("%s\n", s);

有人知道一种符合 ANSI 标准的方法吗?

【问题讨论】:

    标签: c


    【解决方案1】:

    对于您想使用 ECHO 标志的类 UNIX 系统...

    #include <termios.h>
    ...
    struct termios t;
    tcgetattr(fd, &t);
    t.c_lflag &= ~ECHO;
    tcsetattr(fd, TCSANOW, &t);
    ...
    

    【讨论】:

    • t.c_lflag |= ~ECHO 应该是 t.c_lflag &= ~ECHO
    • fd 就是STDIN_FILENO
    • STDIN_FILENO 就是0
    【解决方案2】:

    也许你可以这样尝试:

    #include<stdio.h>
    char s[100];
    system("stty -echo");
    scanf("%s",s); /* Won't echo to screen while being typed */
    system("stty echo");
    printf("You have entered:");
    printf("%s\n", s);
    return 0;
    }
    

    在Linux中,系统功能“stty -echo”是不回显的输入某事。希望这会有所帮助。

    【讨论】:

      【解决方案3】:

      您不能使用 ANSI C 以跨平台方式执行此操作。您必须使用一些特定于操作系统的代码,或使用诸如 ncurses 之类的库。

      【讨论】:

        【解决方案4】:

        getpass 命令存在于 Linux 中。但是您可以制作一个更漂亮的版本,单独的系统回显不会消除对输入命令的需求,而取消缓冲并不会消除数据输入后回车的产生。将两者结合起来可以很好地近似安静的进入。您可以添加一个星号来显示一个秘密条目,所以这里是两个建议的组合:

            #include <stdio.h>
            #include <termios.h>
            #include <unistd.h>
            int getche(void);
            int main(int argc, char **argv){
            int i=0;       
            char d,c='h',s[6];
            printf("Enter five secret letters\n");
            s[5]='\0'; //Set string terminator for string five letters long
            do{
              d=getche();//Fake getche command silently digests each character
            printf("*");
              s[i++]=d;} while (i<5);
            printf("\nThank you!!\n Now enter one more letter.\n");
            c=getchar();
            printf("You just typed %c,\nbut the last letter of your secret string was %c\n",c,d);   
            printf("Your secret string was: %s\n",s);   
                return 0;
            }
            /* reads from keypress, echoes */
                int getche(void)
                {
                    struct termios oldattr, newattr;
                    int ch;
                    tcgetattr( STDIN_FILENO, &oldattr );
                    newattr = oldattr;
                    newattr.c_lflag &= ~( ICANON | ECHO);\\knock down keybuffer
                    tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
                    system("stty -echo");\\shell out to kill echo
                    ch = getchar();
                    system("stty echo");
                    tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
                    return ch;
                }
        

        【讨论】:

        • -1 尝试缩进您的代码并使用 // 表示 cmets。 \\ 无法编译。
        【解决方案5】:

        ANSI 和 ISO C 没有定义此功能,但是大多数 C 编译器都有 getch() 或类似的变体。

        您需要为您使用的每个编译器进行预处理器定义,该编译器具有不同的库和函数。这并不难,尽管您可能会认为这很烦人。

        -亚当

        【讨论】:

        • getch() 是否阻止终端回显字符?我认为它只对抓取控制键和常规字符有用。
        • C 编译器没有 getch(),这是 curses 库的一部分。而且 getch() 不一定是回显,但是你必须使用其他的curses库函数来关闭回显。否则默认回显。
        • getch() 也是 windows 中 conio.h 的一部分,默认不回显。
        【解决方案6】:

        由于您的任务相当基本,如果幸运的话,您的系统将拥有getpass() 函数:

        char * getpass(const char *prompt);
        

        如果您不想要提示,请执行以下操作:

        char *s = getpass("");
        if (s != NULL)
            printf("Your password was %s!\n", s);
        

        getpass(),与所有与回显和缓冲相关的 C 函数一样,是非标准的,但存在于 Mac OS X 上,可能是 Linux,并且列在 GNU C 库中,因此它可能存在于任何使用 glibc 的系统上.

        如前所述,ANSI 和 ISO 标准没有指定一种标准方式来读取输入而不回显,或者读取无缓冲的输入(即一次一个字符)。

        【讨论】:

        • 在 Mac OS X 10.7.5 上,getpass() 返回一个无效的指针,如果你尝试使用它会导致程序崩溃。
        • @Michael - 我自己还在使用 Snow Leopard,但当时我写道,普通的老 Leopard 是最新的 OS X。奇怪的是事情的变化......
        • 不知道为什么,但问题是编译器正在生成 64 位代码,但正在链接 32 位版本的 getpass()。由于 getpass() 是 libc 的一部分,我不知道为什么会这样。 (编译为 32 位可以解决问题)
        【解决方案7】:

        没有; ANSI C 和 ISO C++ 都没有这样的东西。

        【讨论】:

          【解决方案8】:

          这取决于您的环境,这不是语言提供的。如果您打算进行广泛的字符模式 I/O,您可能会查看类似 curses 之类的库。否则,您将不得不手动操作终端或 Windows 控制台。

          【讨论】:

            猜你喜欢
            • 2017-11-02
            • 2013-03-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-01-17
            • 2014-12-22
            相关资源
            最近更新 更多