Reputation: 1219
The title is misleading because I'm more interested in finding an alternate solution. My gut feeling is that checking whether the buffer is empty is not the most ideal solution (at least in my case).
I'm new to C++ and have been following Bjarne Stroustrup's Programming Principles and Practices using C++. I'm currently on Chapter 7, where we are "refining" the calculator from Chapter 6. (I'll put the links for the source code at the end of the question.)
Basically, the calculator can take multiple inputs from the user, delimited by semi-colons.
> 5+2; 10*2; 5-1;
= 7
> = 20
> = 4
>
But I'd like to get rid of the prompt character ('>') for the last two answers, and display it again only when the user input is asked for. My first instinct was to find a way to check if the buffer is empty, and if so, cout the character and if not, proceed with couting the answer. But after a bit of googling I realized the task is not as easy as I initially thought... And also that maybe that wasn't a good idea to begin with.
I guess essentially my question is how to get rid of the '>' characters for the last two answers when there are multiple inputs. But if checking the cin buffer is possible and is not a bad idea after all, I'd love to know how to do it.
Source code: https://gist.github.com/Spicy-Pumpkin/4187856492ccca1a24eaa741d7417675
Header file: http://www.stroustrup.com/Programming/PPP2code/std_lib_facilities.h
^ You need this header file. I assume it is written by the author himself.
Edit: I did look around the web for some solutions, but to be honest none of them made any sense to me. It's been like 4 days since I picked up C++ and I have a very thin background in programming, so sometimes even googling is a little tough..
Upvotes: 4
Views: 7038
Reputation: 118300
As you've discovered, this is a deceptively complicated task. This is because there are multiple issues here at play, both the C++ library, and the actual underlying file.
std::cin
, and C++ input streams, use an intermediate buffer, a std::streambuf
. Input from the underlying file, or an interactive terminal, is not read character by character, but rather in moderately sized chunks, where possible. Let's say:
int n;
std::cin >> n;
Let's say that when this is done and over is, n
contains the number 42
. Well, what actually happened is that std::cin
, more than likely, did not read just two characters, '4' and '2', but whatever additional characters, beyond that, were available on the std::cin
stream. The remaining characters were stored in the std::streambuf
, and the next input operation will read them, before actually reading the underlying file.
And it is equally likely that the above >>
did not actually read anything from the file, but rather fetched the '4' and the '2' characters from the std::streambuf
, that were left there after the previous input operation.
It is possible to examine the underlying std::streambuf
, and determine whether there's anything unread there. But this doesn't really help you.
If you were about to execute the above >>
operator, you looked at the underlying std::streambuf
, and discover that it contains a single character '4', that also doesn't tell you much. You need to know what the next character is in std::cin
. It could be a space or a newline, in which case all you'll get from the >>
operator is 4. Or, the next character could be '2', in which case >>
will swallow at least '42', and possibly more digits.
You can certainly implement all this logic yourself, look at the underlying std::streambuf
, and determine whether it will satisfy your upcoming input operation. Congratulations: you've just reinvented the >>
operator. You might as well just parse the input, a character at a time, yourself.
You determined that std::cin
does not have sufficient input to satisfy your next input operation. Now, you need to know whether or not input is available on std::cin
.
This now becomes an operating system-specific subject matter. This is no longer covered by the standard C++ library.
This is doable, but in all practical situations, the best solution here is to use an operating system-specific approach, instead of C++ input streams, and read and buffer your input yourself. On Linux, for example, the classical approach is to set fd 0 to non-blocking mode, so that read()
does not block, and to determine whether or not there's available input, just try read()
it. If you did read something, put it into a buffer that you can look at later. Once you've consumed all previously-read buffered input, and you truly need to wait for more input to be read, poll()
the file descriptor, until it's there.
Upvotes: 1