Как я могу сгенерировать BACKSPACE в консоли отладки Visual Studio? - PullRequest
0 голосов
/ 11 апреля 2020

Я пишу программу Windows в режиме консоли C с использованием сообщества Visual Studio 2019. Я хочу, чтобы каждое обратное пространство, видимое во входном потоке, было напечатано как литерал строка "\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);

Ответы [ 2 ]

1 голос
/ 12 апреля 2020

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 как \r и для getchar() не возвращаться при нажатии ENTER до тех пор, пока не будет введен следующий символ. Без сомнения, есть решение для этого, но я оставлю это для вас, чтобы экспериментировать. Это может быть конфликт между тем, что обработка stdin и Windows консольная обработка - и, возможно, использование функций ввода-вывода ReadConsole() и Win API вообще может помочь?

0 голосов
/ 13 апреля 2020

У меня есть рабочее решение с использованием 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;
}
...