c - fgetc 需要 'enter' 在 WINDOWS 上按两次键

标签 c windows passwords fgetc

我正在尝试制作一个可在 Windows、Linux 和 osx 之间移植的密码输入掩码函数。到目前为止,我的代码可以在 linux 和 osx 中完美运行,但 Windows 给我带来了一个问题。

有谁知道为什么在 Windows 中 fgetc 要求我在退出 while 循环之前按 enter 键两次?

static int get_password(char *password, int mask)
{
    int max_pass_len = 512;

#ifdef _WIN32
    HANDLE hstdin = GetStdHandle(STD_INPUT_HANDLE);
    DWORD mode = 0;
    DWORD prev_mode = 0;
    GetConsoleMode(hstdin, &mode);
    GetConsoleMode(hstdin, &prev_mode);
    SetConsoleMode(hstdin, mode & ~(ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT));
#else
    static struct termios prev_terminal;
    static struct termios terminal;

    tcgetattr(STDIN_FILENO, &prev_terminal);

    memcpy (&terminal, &prev_terminal, sizeof(struct termios));
    terminal.c_lflag &= ~(ICANON | ECHO);
    terminal.c_cc[VTIME] = 0;
    terminal.c_cc[VMIN] = 1;
    tcsetattr(STDIN_FILENO, TCSANOW, &terminal);
#endif

    size_t idx = 0;         /* index, number of chars in read   */
    int c = 0;

    const char BACKSPACE = 8;
    const char RETURN = 13;

    /* read chars from fp, mask if valid char specified */
    while (((c = fgetc(stdin)) != '\n' && c != RETURN && c != EOF && idx < max_pass_len - 1) ||
            (idx == max_pass_len - 1 && c == 127))
    {
        if (c != 127 && c != BACKSPACE) {
            if (31 < mask && mask < 127)    /* valid ascii char */
                fputc(mask, stdout);
            password[idx++] = c;
        } else if (idx > 0) {         /* handle backspace (del)   */
            if (31 < mask && mask < 127) {
                fputc(0x8, stdout);
                fputc(' ', stdout);
                fputc(0x8, stdout);
            }
            password[--idx] = 0;
        }
    }
    password[idx] = 0; /* null-terminate   */

// go back to the previous settings
#ifdef _WIN32
    SetConsoleMode(hstdin, prev_mode);
#else
    tcsetattr(STDIN_FILENO, TCSANOW, &prev_terminal);
#endif

    return idx; /* number of chars in passwd    */
}

```

最佳答案

使用 ReadConsole 解决了问题

#ifdef _WIN32
    long unsigned int char_read = 0;
    while ((ReadConsole(hstdin, &c, 1, &char_read, NULL) && c != '\n' && c != RETURN && c != EOF && idx < max_pass_len - 1) ||
            (idx == max_pass_len - 1 && c == BACKSPACE))
#else
    while (((c = fgetc(stdin)) != '\n' && c != EOF && idx < max_pass_len - 1) ||
            (idx == max_pass_len - 1 && c == 127))
#endif

关于c - fgetc 需要 'enter' 在 WINDOWS 上按两次键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44376492/

相关文章:

Java用户名和密码总是返回true

c++ - 序列点和偏序

c - fseek() 导致数据重叠

.net - 如何卸载 dotnet 6?

c++ - 如何将现有代码/位图分配给 MFC

android - 使用 phonegap 在 Android 应用程序中覆盖密码字段

c# - WebMatrix WebSecurity 密码盐

c++ - 有没有办法在输出二进制文件中存储 clang 编译时标志?

c - C语言中的内存分段

windows - 将 powershell 输出导出到文本文件