23

I'm fairly new to C++ and have been learning things like this:

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

Messing around with cin, I have come across a roadblock.

Say I wanted to write "I am x years old!".

"x" being cin >> age;

I write the code like this.

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

The roadblock is that this produces a line break.

I don't want the line break.

How can I have all this stay on one line?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
JimGordon
  • 385
  • 3
  • 8
  • 4
    This doesn't make much sense to me. Shouldn't you *first* ask the user to input the age and then output `std::cout << "I am " << x << " years old.\n"` as a whole? – 5gon12eder Dec 14 '15 at 23:36
  • So are you trying to come up with something like a blank into which the user can input their age? If so, unfortunately, that's not how text-based systems generally work, but I'm sure that this could be done with [ncurses](https://en.wikipedia.org/wiki/Ncurses), although it would become more complicated. – Numeri Dec 14 '15 at 23:41
  • 1
    The way to input something without a newline is to turn off buffering on the stream. But that depends on what OS you are using and isn't part of C++. For example in Windows you can get characters without echoing them to the screen at all and then decide later which ones to put on the screen. – Jerry Jeremiah Dec 14 '15 at 23:41
  • 2
    #Numeri points out what I want to do. Fill-in-the-blank with cin. #DietmarKuhl explains that this is possible but will be a bit of work. I realize, with my knowledge, I am limited to using the cin logic #Olipro presents. – JimGordon Dec 15 '15 at 00:02
  • ###It is possible! If you're using **[Microsoft Visual Studio](http://en.wikipedia.org/wiki/Microsoft_Visual_Studio)**, and, therefore, can use the header `conio.h`, then there's a solution (but it might be a bit tricky since you need to deal with characters, not streams). Take a look at [this answer to similar question on Stack Overflow](http://stackoverflow.com/a/29042866/4789373). **PS:** After getting the characters that you need, you can go back and use streams to read out an integer value from it. – Chan Kha Vu Dec 14 '15 at 23:54

5 Answers5

23

I assume you actually want the input to be in line with with the eventual output. Otherwise, the solution is trivial: first read the value and then print it, e.g.:

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

Dealing with input which is in line with the output is a bit more tricky. The issue here is that the console handling is actually done by the system and not by the language. As a result, it is necessary to wait for a newline when entering data. The newline will be handled by the console and create a line break. To disable this behavior it is necessary to work around relying on the console behavior. There is no standard C++ way of doing so.

I don't know how to deal with console controls on Windows: I'm primarily a UNIX programmer. On a UNIX system you'd use tcgetattr() and tcsetattr() to set the input mode to be non-canonical (i.e., to clear the ICANON bit). The required file descriptor is simply the one for the standard input, i.e., 0.

Once the console is using non-canonical mode all key presses are immediately forwarded to application and no screen echo is done. As a result, the reading function will actually need to echo individual characters and then forward then to a parsing function. The easiest way to do is to create a filtering stream buffer which does the necessary echoing for std::cin to std::cout while forwarding the character. However, putting all of that together is a bit of work...

When cooking a demo I noticed that I also needed to deal with echoing (to avoid a newline when the user uses the enter key). It is also important to reset the console flags as some of them actually stay changed even after the program terminates. An implementation putting the bits together but still lacking error handling could look like this:

#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";
    }
}
user2357112
  • 260,549
  • 28
  • 431
  • 505
Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • 2
    Just for completeness, the Windows equivalent would be [`SetConsoleMode`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033.aspx) with `ENABLE_LINE_INPUT` and `ENABLE_ECHO_INPUT` disabled. Then [`ReadConsole`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms684958.aspx) (or `ReadFile` with stdin) can be used. – Bob Dec 15 '15 at 01:40
  • 1
    @Mawg While this may not be an authoritative source, [cppreference.com](http://en.cppreference.com/w/cpp/io/manip/endl) has a note about `std::endl` that says "Use of std::endl in place of '\n', encouraged by some sources, may significantly degrade output performance." So that might be what's with the `\n`. – Alex Dec 15 '15 at 13:26
  • 1
    @Mawg: `\n` is perfectly valid C++. You might prefer `std::endl`, but you shouldn't spam the Stack Overflow comments to any answer that uses a coding convention you dislike. Also, note that `\n` and `std::endl` technically don't even do exactly the same thing, as explained in Alex's link. – FrederikVds Dec 15 '15 at 13:40
  • Agreed; they don't do the same thing. Which is why one should use `std::endl`. In specific cases, when you know exactly what you want to do, `\n` is acceptable, but here we are trying to teach a newcomer good coding practices. – Mawg says reinstate Monica Dec 15 '15 at 13:43
  • In specific cases, `\n` is not only acceptable, but the only option. In other specific cases, you need std::endl instead. In most cases, either is acceptable. I see no reason to assume that in this case only std::endl would be acceptable. The idea that `std::endl` is a better coding practice in the large majority of cases where both would work is entirely subjective. You shouldn't upvote incorrect answers just because they follow your preferred coding practices, or spam correct answers because they don't. – FrederikVds Dec 15 '15 at 13:56
  • 1
    @Mawg: funny you shall say that I should use `std::endl`. Note, however, that my use of `'\n'` is rather deliberate. For reason you may want to have a look at a [blog](http://kuhllib.com/2012/01/14/stop-excessive-use-of-stdendl/) I wrote a fear years ago. In particular, I object strong to the notion that newcomers should be thought to use `std::endl`: nobody should use `std::endl` ever is the correct assessment. – Dietmar Kühl Dec 15 '15 at 14:02
11

cin reads input after a newline is entered onto the console.

Therefore the only way you can do it continuously is to prompt the user for their age and then proceed to write it.

e.g:

std::cout << "Enter your age> ";
std::cin >> age;
std::cout << "I am " << age << " years old" << std::endl;
Olipro
  • 3,489
  • 19
  • 25
10
unsigned int age;
std::cin >> age;

std::cout << "I am " << age << " years old!" << std::endl;
erip
  • 16,374
  • 11
  • 66
  • 121
6

You cannot do what you want in pure C++. You can do as others suggested and reprint the line:

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

Or you can use an OS-specific function to clear the console output. Read about this here.

For example, you could use system("cls"); for Windows, to clear the console after asking the user their age.

#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"
    ...
}

Yields:

C:>AgeProgram.exe I am 10 years old

Community
  • 1
  • 1
Fantastic Mr Fox
  • 32,495
  • 27
  • 95
  • 175
  • @Mawg `std::endl` flushes the `cout` buffer. In very few cases do you actually want this. `"\n"` and `endl` are the same in every other respect. [Read this.](http://stackoverflow.com/questions/213907/c-stdendl-vs-n) – Fantastic Mr Fox Dec 15 '15 at 17:03
0

you can do like this

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
Sarthak Doshi
  • 424
  • 4
  • 8