1

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?

Zebrafish
  • 11,682
  • 3
  • 43
  • 119
  • 1
    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 Dec 23 '16 at 20:43
  • 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 Dec 23 '16 at 23:45

2 Answers2

4

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.

Community
  • 1
  • 1
wally
  • 10,717
  • 5
  • 39
  • 72
  • OK, that's a cool trick. But I only see '\n' for line endings. I thought Windows was supposed to use '\r' '\n' for line endings, for example when making a notepad document. I assumed the console would be the same. – Zebrafish Dec 23 '16 at 21:04
  • That is weird. Thank you so much. Another rule/exception I'll have to add to my head. – Zebrafish Dec 23 '16 at 21:20
0

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;
    }
}
Jas
  • 850
  • 7
  • 21
  • Doesn't seem to work, if I type in hello in the console that switch loop just couts hello. I think this is because what's in the std::string is just hello, that's it, it never copied any '\r' or '\n' to it. – Zebrafish Dec 23 '16 at 20:51
  • Oh my bad I see. But if thats the case then the buffer technically doesn't have the '\n' I suppose. I am guessing the stream just cuts off the string at '\n' and puts a '\0' terminator in that place since the _line_ does end there. – Jas Dec 23 '16 at 21:01
  • Looking at this more carefully, I just realized I misinterpreted your question sorry. I assumed by input buffer you meant the string itself. I believe Mus campester's answer is what you are looking for. – Jas Dec 23 '16 at 21:06
  • Yeah you're right, in the case where it copies it to a char pointer, you can see that it's chopped off the '\n' and null terminated it. But I thought Windows line endings were '\r' '\n', and I wanted to see this, doesn't seem so from the other answer, that is, it seems there is only a '\n'. – Zebrafish Dec 23 '16 at 21:07