2015-12-14 2 views
22

Я довольно новыми для C++ и изучаю вещи, как это:Как использовать cin между строками в C++?

cout << "My age is: "; 
cin >> age; 

Мессинг вокруг с CIN, я пришел через контрольно-пропускной пункт.

Скажем, я хотел написать «Мне x лет!».

«x» cin >> возраст;

Я пишу код следующим образом.

cout << "I am "; 
cin >> age; 
cout << "years old!"; 

Дорожный блок состоит в том, что это создает разрыв линии.

Я не хочу, чтобы линия прерывалась.

Как я могу все это остаться на одной линии?

+4

Это не имеет большого смысла для меня. Не следует ли вам сначала * просить пользователя ввести возраст, а затем вывести 'std :: cout <<« Я «<< x <<» лет. \ N "' в целом? – 5gon12eder

+0

Так вы пытаетесь придумать что-то вроде пробела, в который пользователь может ввести свой возраст? Если это так, к сожалению, это не так, как обычно работают текстовые системы, но я уверен, что это можно сделать с помощью [ncurses] (https://en.wikipedia.org/wiki/Ncurses), хотя это будет больше сложно. – Numeri

+1

Способ ввода чего-либо без новой строки - отключить буферизацию потока. Но это зависит от того, какую ОС вы используете и не являетесь частью C++. Например, в Windows вы можете получить символы без повторения их на экране вообще, а затем решить, какие из них будут помещаться на экран. –

ответ

8
unsigned int age; 
std::cin >> age; 

std::cout << "I am " << age << " years old!" << std::endl; 
+0

Это только способ избежать этой проблемы, а не решения. – FalconUA

+3

Что? Это не имеет смысла ... – erip

+0

Плюс один для того, чтобы быть единственным, кто использовал 'std :: endl', а не' \ n' – Mawg

11

cin считывает ввод после ввода новой строки на консоль.

Таким образом, единственный способ, которым вы можете это сделать, - пригласить пользователя на их возраст, а затем продолжить его запись.

например:

std::cout << "Enter your age> "; 
std::cin >> age; 
std::cout << "I am " << age << " years old" << std::endl; 
+1

вы можете ссылаться на новую строку? – dhein

22

Я предполагаю, что вы на самом деле хотите, чтобы вход, чтобы быть в соответствии с с возможным выходом. В противном случае решение тривиально: сначала считывать значение, а затем распечатать его, например .:

std::cout << "how old are you? "; 
std::cin >> x; 
std::cout << "I am " << x << " years old\n"; 

Работа с входом, который находится в соответствии с выходным сигналом является немного более сложным. Проблема здесь в том, что обработка консоли фактически выполняется системой, а не языком. В результате при вводе данных необходимо дождаться новой строки. Новая строка будет обрабатываться консолью и создать разрыв строки. Чтобы отключить это поведение, необходимо работать, опираясь на поведение консоли. Для этого нет стандартного C++.

Я не знаю, как иметь дело с консольными элементами управления в Windows: я в первую очередь программист UNIX. В системе UNIX вы должны использовать tcgetattr() и tcsetattr(), чтобы установить режим ввода неканоническим (то есть, чтобы очистить бит ICANON). Требуемый файловый дескриптор - это просто стандартный для ввода, т. Е. 0.

После того, как консоль использует неканонический режим, все нажатия клавиш сразу же перенаправляются в приложение, и экранное эхо не выполняется. В результате функция чтения действительно должна будет эхо-символа отдельных символов, а затем переходить к функции синтаксического анализа. Самый простой способ - создать буфер фильтра потока, который выполняет эхо-запрос для std::cin до std::cout при пересылке символа. Тем не менее, все это вместе - немного работы ...

При подготовке демонстрации я заметил, что мне также нужно иметь дело с эхом (чтобы избежать новой строки, когда пользователь использует клавишу ввода). Также важно сбросить флаги консоли, поскольку некоторые из них фактически остаются измененными даже после завершения программы.Реализация положить биты вместе, но по-прежнему не хватает обработки ошибок может выглядеть следующим образом:

#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"; 
    } 
} 
+2

Для полноты эквивалента Windows будет ['SetConsoleMode'] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033.aspx) с' ENABLE_LINE_INPUT' и 'ENABLE_ECHO_INPUT' отключены. Затем можно использовать [ReadConsole] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms684958.aspx) (или 'ReadFile' с помощью stdin). – Bob

+1

@Mawg Хотя это не может быть авторитетным источником, [cppreference.com] (http://en.cppreference.com/w/cpp/io/manip/endl) имеет примечание о 'std :: endl', которое говорит «Использование std :: endl вместо« \ n », вызванное некоторыми источниками, может значительно ухудшить производительность вывода». Так может быть и с '\ n'. – Alex

+1

@Mawg: '\ n' отлично подходит для C++. Вы можете предпочесть 'std :: endl', но вы не должны спамить комментарии Stack Overflow на любой ответ, который использует непринятое вами кодирование. Также обратите внимание, что '\ n' и' std :: endl' технически даже не делают точно то же самое, что объясняется в связи с Alex. – FrederikVds

6

Вы не можете делать то, что вы хотите в чистом C++. Вы можете сделать, как другие предложили и перепечатать строку:

std::cout << "I am " << age << " years old!\n" 

Или вы можете использовать функцию OS специфический для очистки выхода консоли. Read about this here.

Например, вы можете использовать system("cls"); для Windows, чтобы очистить консоль, попросив у пользователя их возраст.

#include <stdlib.h> 

int main(int argc, char* argv[]) { 
    unsigned int age; 
    std::cout << "My age is: " 
    std::cin >> age; 
    system("cls"); 
    std::cout << "I am " << age << " years old!\n" 
    ... 
} 

Урожайность:

C:>AgeProgram.exe I am 10 years old

+0

@Mawg 'std :: endl' очищает буфер' cout'. В очень немногих случаях вы действительно этого хотите. '' \ n "' и 'endl' одинаковы во всех остальных отношениях. [Read this.] (Http://stackoverflow.com/questions/213907/c-stdendl-vs-n) –

0

вы можете сделать, как этот

int user_age; 

std:cout<<"Enter Your Age:"   //Ask user for age 

std::cin >>user_age;    //Read user input 
std::cout<<"I am"<<user_age<<"years old!"<< std::endl; //finlly display the value