How can I see exactly what's in std::cin input buffer?

5.3k views Asked by At

The problem I'm having is that I want to see exactly what's in the input buffer when a person types something into the console The only way I know how to see it is by either std::cin::getline() or std::getline(), but I think both of these write to either a char pointer or std::string object based on what system-specific end-of-line characters are appropriate. For example, I think on Windows if you hit enter on the console it'll input '\r''\n', but when I try to read it from the char pointer or the string object they don't show any '\r'. For example if I type the word hello in the console, I suspect that windows puts:

'h' 'e' 'l' 'l' 'o' '\r' '\n'

into the buffer, but in the char pointer or the string object I only see "hello". I basically want to SEE what's in the input buffer. Can I extract each character from the buffer one by one in a loop, in a way that it doesn't throw out whitespace characters?

2

There are 2 answers

4
Jas On

I think this should work:

std::string mystring;
std::cin >> mystring;

for(unsigned int i = 0; i < mystring.size(); i++)
{
    switch(mystring[i])
    {
        case ‘\n’:
            cout << “\\n”; // print \n by escaping the slash
            break;
        case ‘\r’:
            cout << “\\r”; // print \r by escaping the slash
            break;
        // OTHER CASES HERE
        default:
            cout << mystring[i]; // print the string normally
            break;
    }
}
2
wally On

std::cin is a std::basic_istream and can be manipulated as such.

Normally, you would read the stream with >> or getline for example. Both of those reads "know when to stop".

But if you want to peek at the buffer with the \ns then that assumes that you will pass the stream from the console with the newline characters and that the functions you are using to read it will not "eat" the newlines.

You can copy the buffer to a string. But remember that you will have to signal the EOF in some other way.

#include <iostream>
#include <string>
#include <sstream>

int main() {
    std::ostringstream oss{};
    oss << std::cin.rdbuf();
    std::string all_chars{oss.str()};
    std::cout << all_chars;
    return 0;
}

On windows, if I type helloEnterthereEnter followed by Ctl+z (must be on a new line for windows) then I see:

hello
there
^Z
hello
there

So in this example, everything including the newlines was stored in the std::string.


But I only see \n for line endings. I thought Windows was supposed to use \r \n for line endings

I added the following to show the individual characters explicitly:

int index{};
for(auto mychar : all_chars)
    std::cout << std::setw(3) << index++ << ": character number " << std::setw(5) << static_cast<int>(mychar) 
        << " which is character\t"<< ((mychar == 10) ? "\\n" : std::string{}+mychar) << '\n';

For the same input it produces:

hello
there
^Z
hello
there
  0: character number   104 which is character  h
  1: character number   101 which is character  e
  2: character number   108 which is character  l
  3: character number   108 which is character  l
  4: character number   111 which is character  o
  5: character number    10 which is character  \n
  6: character number   116 which is character  t
  7: character number   104 which is character  h
  8: character number   101 which is character  e
  9: character number   114 which is character  r
 10: character number   101 which is character  e
 11: character number    10 which is character  \n

So this shows that only \ns are passed from the console, no \rs to be found. I used Windows 10 for this test, but I suppose this has been the behavior for a while.