1
votes

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
Generally, not possible with standard C++. On systems where it matters, you can sometimes get away with closing and reopening std::cin in binary mode, and then use read() to get characters. But that is not guaranteed by the standard. - Peter
For text streams (i.e., file streams not opened with std::ios_base::binary) the platform-specific line end sequence is translated into \n when reading. When writing to these streams the opposite operation is applied. That is, on Windows when reading \r\n it gets translated into \n. The standard stream objects normally behave like file streams opened in text mode. The standard doesn't actually mandate the exact behavior for the standard stream objects. - Dietmar Kühl

2 Answers

4
votes

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.

0
votes

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;
    }
}