【问题标题】:How can I generate an BACKSPACE in a visual studio debug console?如何在 Visual Studio 调试控制台中生成 BACKSPACE?
【发布时间】:2020-04-11 19:08:22
【问题描述】:

我正在使用 Visual Studio 2019 社区编写 Windows 控制台模式 C 程序。我希望输入流中看到的每个退格键都打印为输出中的 literal 字符串 "\b"

如何将退格信号捕获到控制台?如果我按 CTRL-H 它会删除前面的字符,但实际上我要 getchar() 来获取相应的值。

while ((c = getchar()) != EOF) {
    if (c == '\t') {
        printf("\\t");
    }
    else if (c == '\b')
        printf("\\b");
    else if (c == '\\') {
        printf("\\\\");
    }
    else
        putchar(c);

【问题讨论】:

  • 完全不清楚你在问什么 '\b' 是后退空格字符 - 要替换​​什么? Ctrl-H 是退格的标准 ASCII CTRL 序列,它适用于 Windows cmd 和 powershell,但退格也是如此。我不知道“Visual Studio 调试控制台”指的是什么。你实际上是在使用 VS Code 而不是 VS?
  • 在 Windows cmd 控制台中也是 8printf("Hello%cu", 8); 输出Hellu
  • @Clifford,我希望我已经做出了有用的澄清。

标签: c visual-studio getchar putchar


【解决方案1】:

Windows 控制台对标准输入执行行编辑处理,允许您使用退格、删除、左/右光标和插入/覆盖模式。这些字符和按键不会导致字符被插入到输入流中。

您可以使用 Win API SetConsoleMode() 关闭输入处理。例如下面我已经切换了处理和行输入模式,以便getchar()在输入每个字符后返回:

#include <stdio.h>   
#include <windows.h>

int main()
{
    HANDLE stdin_handle = GetStdHandle(STD_INPUT_HANDLE); 
    DWORD console_mode = 0 ;
    if( GetConsoleMode( stdin_handle, &console_mode) )
    { 
        console_mode = console_mode & ~(ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT) ;
        SetConsoleMode( stdin_handle, console_mode ) ;
    }

    int c = 0 ;
    while( (c = getchar()) != EOF )
    {     
        switch( c )
        {
            case '\t' : printf( "\\t" ); break ;
            case '\b' : printf( "\\b" ); break ;
            case '\\' : printf( "\\\\" ); break ;
            case '\r' : putchar( '\n' ); break ; // Translate ENTER into Newline
            default : putchar( c ); break ;
        }
    }
}

但是,它可能具有不良的副作用,例如导致 ENTER 被解释为 \rgetchar() 在按下 ENTER 直到输入下一个字符后才返回。毫无疑问,有一个解决方案,但我会留给你去试验。这可能是标准输入处理和 Windows 控制台处理之间的冲突——也许使用 ReadConsole() 和 Win API 控制台 I/O 函数一般会有帮助?

【讨论】:

  • 感谢您的指导,它有帮助。我想知道我是否在 *nix 中面临类似的任务,我该如何处理它。是否有用于规避 *nix shell 及其行编辑处理的非标准 C 头文件或库?也许 GNU Readline 就是这样一种资源。我正在解决的问题是“C 编程语言(第 2 版)”中的一个练习。我假设练习的设计者正在使用视频终端,因此可以只使用标准 (ANSI) C。
  • @Edmund 这可能是一个新问题的主题。 SO 不是论坛,请避免在 cmets 中讨论问题。
【解决方案2】:

我有一个使用 Win API 和 ReadConsole 的有效解决方案。

#include <Windows.h>
#include <stdlib.h> 
#include <stdio.h>

BOOL readInput(HANDLE hConsoleInput, TCHAR chBuffer, DWORD nNumberOfCharsToRead);

int main(void)
{
    DWORD console_mode = 0;
    HANDLE stdin_handle;
    TCHAR chBuffer = 0;

    stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
    if (GetConsoleMode(stdin_handle, &console_mode))
    {
        console_mode = console_mode & ~(ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT);
        SetConsoleMode(stdin_handle, console_mode);
    }

    if (stdin_handle == INVALID_HANDLE_VALUE) {
        printf("Error getting the handle to the console.\n");
        exit(EXIT_FAILURE);
    }

    while (readInput(stdin_handle, chBuffer, 1)) {
        ;
    }

    CloseHandle(stdin_handle);

    return 0;
}

BOOL readInput(HANDLE hConsoleInput, TCHAR chBuffer, DWORD nNumberOfCharsToRead)
{
    DWORD dwCount;
    BOOL bSuccess;

    bSuccess = ReadConsole(hConsoleInput, &chBuffer, nNumberOfCharsToRead, &dwCount, NULL);

    if (!bSuccess) {
        printf("Error reading from the console.\n");
        exit(EXIT_FAILURE);
    }

    switch (chBuffer)
    {
        case '\t':
            printf("\\t");
            break;
        case '\b':
            printf("\\b");
            break;
        case '\\':
            printf("\\\\");
            break;
        case '\r':
            putchar('\n');
            break;
        case '\x1a':                //EOF
            return FALSE;
        default:
            putchar(chBuffer);
            break;
        }

    return TRUE;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-23
    • 1970-01-01
    • 1970-01-01
    • 2019-11-18
    • 1970-01-01
    • 1970-01-01
    • 2020-11-09
    • 1970-01-01
    相关资源
    最近更新 更多