例如,当使用GitHub CLI时,它们提示你如下:
Do something? (Y/n)
,如果你要输入n
并按'Enter',那么输出将变为:
Do something? No
'Next line's content'
我想在我的程序中做类似的事情。
在我的用例中,它看起来像:Row 1: 1 2 3
Row 2: 4 5 6
Row 3: 7 8 9
Row 4:
,其中用户输入整数,按'Enter',现在在Row 4:
上。
当用户按下'Enter'时,我希望它转换成:
Row 1: 1 2 3
Row 2: 4 5 6
Row 3: 7 8 9
Row 4: N/A
,或者最好是:
Row 1: 1 2 3
Row 2: 4 5 6
Row 3: 7 8 9
,但我不确定如何做到这一点,因为用户按"Enter"会把std::out
放在新的行,如果我要打印出N/A
,它看起来像:
Row 1: 1 2 3
Row 2: 4 5 6
Row 3: 7 8 9
Row 4:
N/A
终端应用程序通过向终端发送特殊的控制字符来实现这一点(这是一个非常老派的API!)像ncurses
这样的库和像tput
这样的外部工具可以为你制作奥术咒语,但你自己做并不难。
在这种情况下,一旦用户按下输入,您需要将光标移回到上一行的开头,清除该行的其余部分,并写入您想要的内容。
#define ESC_PREV_LINE "e[F"
#define ESC_CLEAR_TO_END "e[K"
std::cerr << "Row 4: " << std::flush; // traditionally, interactive prompts appear on stderr! this makes it easy to separate the "real" output of a program from the interactive part to e.g. save in a file
// read input...
if(need_to_rewrite_input) {
std::cerr << ESC_PREV_LINE ESC_CLEAR_TO_END "Row 4: 7 8 9n";
}
你可能想在程序开始时检查cerr
是否真的指向终端,如果不是,要么使用回退行为,要么直接退出。
一个选择是使用像ncurses这样的库。例如,如果您想覆盖光标前面的多行输出,这一点尤其重要。
如果您正在寻找更基本的东西(例如,仅影响最后一行的输出,并且没有太多的错误检查,并且不依赖于通常特定于设备的转义码),您可以执行以下操作:
const std::string yesno = "(Y/n)"
char input;
std::cout << "Do something? " << yesno << " ";
std::cin >> input;
if (std::toupper(input) == 'Y')
{
for (std::size_t i = 0; i < yesno.length() + 2; ++i)
std::cout << "b b";
std::cout << 'Y';
std::cout << std::endl;
}
// code that produces next line of output
循环在最后一行备份一个覆盖字符,每次一个。循环中的神奇数字2
来自于需要覆盖空格字符和用户输入的单个字符。
上面的缺点是它假设用户在按回车键之前只输入一个字符。没有办法阻止用户做一些不同的事情(例如,用户可能会在按回车键之前愉快地输入YYYY)。
为了解决这个问题,我们可以这样做
如果你想放松这个假设,下面是可能的
const std::string yesno = "(Y/n)"
std::string input;
std::cout << "Do something? " << yesno << " ";
std::getline(std::cin, input);
if (input.length() > 0 && std::toupper(input[0]) == 'Y')
{
for (std::size_t i = 0; i < yesno.length() + input.length() + 1; ++i)
std::cout << "b b";
std::cout << 'Y';
std::cout << std::endl;
}
// code that produces next line of output
这将处理用户在回车键之前输入YNYN,通过只检查输入的第一个字符,忽略(并覆盖)其余的字符。
以上两个都假设输出一个空格字符将覆盖光标位置的字符)。但是大多数现代终端或控制台(窗口系统中的硬件设备或模拟器)的默认设置与该假设一致。有一些旧设备(大部分已经过时了,现在很少在历史展览或博物馆外看到),这种假设是不成立的[护士通常不会发现,更不用说正确处理这些设备了]。
另一个假设是终端宽度超过用户输入的长度。因此,如果终端/窗口宽度为80个字符,则假定用户在按回车键之前不会输入80个或更多字符。