Ответ 1
Я предполагаю, что вы действительно хотите, чтобы входные данные совпадали с конечным результатом. В противном случае решение тривиально: сначала прочитайте значение и затем распечатайте его, например:
std::cout << "how old are you? ";
std::cin >> x;
std::cout << "I am " << x << " years old\n";
Работа с вводом, который соответствует результату, немного сложнее. Проблема здесь в том, что обработка консоли фактически выполняется системой, а не языком. В результате при вводе данных необходимо дождаться новой строки. Новая строка будет обрабатываться консолью и создать разрыв строки. Чтобы отключить это поведение, необходимо работать, опираясь на поведение консоли. Не существует стандартного способа С++.
Я не знаю, как обращаться с консольными элементами управления в Windows: я в первую очередь программист UNIX. В системе UNIX вы должны использовать tcgetattr()
и tcsetattr()
, чтобы установить режим ввода неканоническим (т.е. Очистить бит ICANON
). Требуемый файловый дескриптор - это просто стандартный для ввода, т.е. 0
.
Когда консоль использует неканонический режим, все нажатия клавиш сразу же перенаправляются в приложение, и эхо-сигнал экрана не выполняется. В результате функция чтения действительно должна будет эхо-символа отдельных символов, а затем переходить к функции синтаксического анализа. Самый простой способ - создать буфер фильтра фильтрации, который выполняет эхо-повторение для std::cin
до std::cout
при пересылке символа. Однако, все это вместе - немного работы...
При приготовлении демонстрации я заметил, что мне также нужно иметь дело с эхом (чтобы избежать новой строки, когда пользователь использует клавишу ввода). Также важно reset консольные флаги, поскольку некоторые из них фактически остаются измененными даже после завершения программы. Реализация, ставящая биты вместе, но все еще без обработки ошибок, может выглядеть так:
#include <iostream>
#include <ctype.h>
#include <termios.h>
struct non_canon_buf
: std::streambuf {
char buffer;
non_canon_buf() {
termios flags = {};
tcgetattr(0, &flags);
flags.c_lflag &= ~(ICANON | ECHO);
tcsetattr(0, TCSANOW, &flags);
}
~non_canon_buf() {
termios flags = {};
tcgetattr(0, &flags);
flags.c_lflag |= ICANON | ECHO;
tcsetattr(0, TCSANOW, &flags);
}
int underflow() {
if (std::cin.get(buffer)) {
this->setg(&buffer, &buffer, &buffer + 1);
if (!std::isspace(static_cast<unsigned char>(buffer))) {
std::cout << buffer << std::flush;
}
return std::char_traits<char>::to_int_type(buffer);
}
return std::char_traits<char>::eof();
}
};
int main()
{
non_canon_buf sbuf;
std::istream in(&sbuf);
std::cout << "I am ";
int age = 0;
in >> age;
std::cout << " years old\n";
if (!in) {
std::cout << "ERROR: failed to enter a valid age!\n";
}
}