正确的逐个字符输入

Proper character by character input?

本文关键字:字符输入      更新时间:2023-10-16

为了更好地熟悉c++,我正在重做一个大学时的操作系统作业:编写自己的shell。我解决的第一件事是接受命令,但我的方法还有一些需要改进的地方。我有:

string GetLine() {
    string line;
    char input = _getch();
    while (input != 13) {
        switch (input) {
        case 8: // backspace
            if (line.length() != 0) {
                line = line.substr(0, line.length() - 1);
                cout << "b b";
            }
            break;
        case -32: // all arrows' first byte
            input = _getch(); // distinctly different arrow byte
            switch (input) {
                case 72: // up
                    break;
                case 80: // down
                    break;
                case 75: // left
                    break;
                case 77: // right
                    break;
            }
            break;
        case 9: // tab
            break;
        default:
            line += input;
            cout << input;
            break;
        }
        input = _getch();
    }
    cout << endl;
    return line;
}

它工作得很好,我知道我有更多的箭头键(如果我甚至正确区分它们)。我要问的主要问题是光标已经换行到终端上的下一行的特定情况。为了模拟cmd.exe,我打印了一个提示符,并在它的末尾等待用户的输入。当这个提示符很长时,在我的命令跨两行运行之前,它只需要几个字符。如果我只是把它打出来,然后换行,然后回车,一切都很好。如果我换行到第二行,并想退格回第一行,光标停在新行上的第一个字符处,而不会像我希望的那样"解行"回第一行。我该怎么做才能实现这种展开行为呢?

我认为问题是试图打印'b'不会展开,但我没有一个替代的想法,我希望我不必将此视为特殊情况,并且在行中间退格的代码也将在行开头工作。

你需要使用winapi, SetConsoleCursorPosition将帮助你。下面是一个将光标从当前位置向上移动一行的最小示例:

#include <iostream>
#include <windows.h> 
int main() {
    std::cout << "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
        "aaaaaaaaaaaaaaa";
    HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_SCREEN_BUFFER_INFO csbiInfo; 
    GetConsoleScreenBufferInfo(hStdout, &csbiInfo);
    csbiInfo.dwCursorPosition.Y -= 1; // Move Y coordinate up by one
    SetConsoleCursorPosition(hStdout, csbiInfo.dwCursorPosition);
    std::cin.get();
}

另外,Console Functions具有控制控制台所需的所有必要函数的完整列表。您将需要在您的程序中使用它们。

你需要用CreateConsoleScreenBuffer创建自己的屏幕缓冲区,然后首先将其设置为缓冲区。然后自己处理从控制台写入和读取的所有内容。