C++: cin.peek(), cin >> char, cin.get(char) - c++

I've got this code with use of cin.peek() method. I noticed strange behaviour, when input to program looks like qwertyu$[Enter] everything works fine, but when it looks like qwerty[Enter]$ it works only when I type double dollar sign qwerty[Enter]$$. On the other hand when I use cin.get(char) everything works also fine.
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
char ch;
int count = 0;
while ( cin.peek() != '$' )
{
cin >> ch; //cin.get(ch);
count++;
}
cout << count << " liter(a/y)\n";
system("pause");
return 0;
}
//Input:
// qwerty$<Enter> It's ok
//////////////////////////
//qwerty<Enter>
//$ Doesn't work
/////////////////////////////
//qwerty<Enter>
//$$ works(?)

It's because your program won't get input from the console until the user presses the ENTER key (and then it won't see anything typed on the next line until ENTER is pressed again, and so on). This is normal behavior, there's nothing you can do about it. If you want more control, create a UI.

Honestly I don't think the currently accepted answer is that good.
Hmm looking at it again I think since, operator<< is a formatted input command, and get() a plain binary, the formatted version could be waiting for more input than one character to do some formatting magic.
I presume it is way more complicated than get() if you look what it can do. I think >> will hang until it is absolutely sure it read a char according to all the flags set, and then will return. Hence it can wait for more input than just one character. For example you can specify skipws.
It clearly would need to peek into more than once character of input to get a char from \t\t\t test.
I think get() is unaffected by such flags and will just extract a character from a string, that is why it is easier for get() to behave in non-blocking fashion.
The reason why consider the currently accepted answer wrong is because it states that the program will not get any input until [enter] or some other flush-like thing. In my opinion this is obviously not the case since get() version works. Why would it, if it did not get the input?
It probably still can block due to buffering, but I think it far less likely, and it is not the case in your example.

Related

using input redirection in while loop

I need to create a program that reads in a list of random integers via input redirection and performs various tasks with them. For the purpose of this question I just want to print the sum of each number + 1. Trouble is, I don’t know how to get it to perform the operation on anything but the first number in the list. My mini program (program.cpp) is
#include <iostream>
using namespace std;
int main () {
int input;
bool arb = true;
cin >> input;
while (arb) {
cout << input + 1 << endl;
}
return 0;
}
and a sample textfile (textfile.txt) I'm using contains
9
8
7
6
When I run it it prints out “10” for infinity. What I’d like it do is print out
10
9
8
7
or the equivalent for whatever other text file may be used.
I thought maybe I could somehow reference specific lines in the textfile, but from searching how to do that all the similar questions I could find seemed to have solutions that required fstream, which is something I haven’t learned yet and therefore I’m not allowed to use it (this is for a class assignment).
The only compiler directives I’ve learned are iostream, string, cmath, iomanip, cstdlib, and ctime. The ways to get input I’ve learned are cin >> input, cin.get(input), and cin.getline(input), so if there are other ways of reading in the file besides those 3 that I’m unaware of, unfortunately I can’t use it. Note that my program HAS to use a while loop. The way the program will be run is
./program < whatevertextfile.txt
which I can't change.
given these restrictions, how can I get my program to read in and use each integer in the text file?
The idiomatic way to read a sequence of white-space separated integers in C++ would be
#include <iostream>
using namespace std;
int main () {
int input;
while (cin >> input) {
cout << input + 1 << endl;
}
return 0;
}
Let's come to why this works the way it does.
cin >> input
discards possible white-space and then reads an integer from the standard input. Moreover, it returns a reference of the cin object used. With this returned reference, you can call the bool conversion operator to check if any of the fail bits is set in the given std::basic_ios object. So
while (cin >> input)
does two things. Read an integer from standard input and check if it successfully completed the operation. As long as this operation succeeds, your while loop continues to iterate and you print the numbers.
See http://en.cppreference.com/w/cpp/io/basic_istream/operator_gtgt for reference on std::basic_istream::operator>>.
See http://en.cppreference.com/w/cpp/io/basic_ios/operator_bool for reference on operator bool.
Edit1: Move references to bottom so that the answer is more readable.

Read in Dollar Amount (with dollar sign) C++

I need to read in a value (cin) including a dollar sign and a dollar amount, but I only want to read in the amount.
In other words, I have this input:
"$3458.5,"
but I want to read in and store
"3458.5"
The current approach I thought of was reading the value in as a string, removing the first character, and then converting to a double. But, I feel like this method is inefficient and there's a better method out there. Any tips? Thanks!
I agree with Magnus: this seems minor. But if you really want to do it, just read a character then read a double:
char ch;
double d;
std::cin >> ch >> d;
if(stream.peek() == '$') stream.get();
stream >> amount;
C++98/03 had a money_get facet to do things like this. Unfortunately, using it was fairly painful (to put it nicely).
C++11 added a get_money manipulator to make life quite a bit simpler. It works something like this:
#include <iostream>
#include <iomanip>
int main() {
long double amt;
std::cin.imbue(std::locale(""));
std::cout.imbue(std::locale(""));
std::cin >> std::get_money(amt);
std::cout << std::showbase << std::put_money(amt) << "\n";
}
Now, there are a couple of things to be aware of here. First and foremost, the conversion from the external to internal representation isn't specified, but in the implementations I've seen, $3458.5 will not be read as 3458.5--it'd be read and stored as 345850 -- that is, a count of the number of pennies.
When you use put_money to write the data back out, however, it'll be converted symmetrically with whatever was done during input, so if you entered $3458.5, it'll be written back out the same way.
There is one other caveat: I've seen at least one implementation that was strangely finicky about input format, so it required either 0 or 2 digits after the decimal point during input, so either $3458.50 or $3458 would read fine, but $3458.5 wouldn't be read at all (it'd be treated as a failed conversion).
If you use scanf instead of cin, you can drop the $ if you know it will always be there and write the information directly to a float.
float d;
scanf("$%f", d);

Why do I get ESC successfully only by _getch()?

I want to do somethings when I press ESC. First I found this: How to read until ESC button is pressed from cin in C++
Then I tried to use cin.get() like answers in that question.
using namespace std;
const int ESC = 27;
char c;
c = cin.get();
if (c == ESC) {
...;
} else {
...;
}
But it never works! cin.get() can get 'a', '1', etc. It just doesn't work When I enter Esc. I've also tried cin >> c and couldn't catch Esc either.
Then I use int _getch( void ); in <conio.h> instead of cin.get(). It works!
_getch() seems to be C-style function, therefore I don't like to use it in C++ codes. And I don't understand why cin.get() doesn't work in my code but it seems to work in others' according to answers in the previous link.
It's on Windows.
Besedes, it's my first time to ask a question in stackoverflow and I haven't mastered English well. Sincerely hope for your answers and comments if I mistook something.
Because std::cin.get() reads characters from the console window, however it is not possible to actually 'write' the escape character; therefor it never catches it.
from cplusplus.com
Internally, the function accesses the input sequence by first constructing a sentry object (with noskipws set to true). Then (if good), it extracts characters from its associated stream buffer object as if calling its member functions sbumpc or sgetc, and finally destroys the sentry object before returning.
To catch the escape key on Windows:
if(GetAsyncKeyState(VK_ESCAPE))
{
//Escape key pressed
}
On Linux you probably have to just use _getch( void ); but I'm not familiar with that.

Why does in_avail() output zero even if the stream has some char?

#include <iostream>
int main( )
{
using namespace std;
cout << cin.rdbuf()->in_avail() << endl;
cin.putback(1);
cin.putback(1);
cout << cin.rdbuf()->in_avail() << endl;
return 0;
} //compile by g++-4.8.1
I think this will output 0 and 2
but when I run the code, it output 0 and 0, why?
or if I change cin.putback(1); to int a; cin >> a; with input 12 12;
it still outputs 0 and 0
Apparently it's a bug/feature of some compiler implementations
Insert the line
cin.sync_with_stdio(false);
somewhere near the beginning of code, and that should fix it
EDIT: Also remember that in_avail will always return 1 more than the number of chars in the input because it counts the end of input character.
EDIT2: Also as I just checked, putback does not work unless you have attempted to read something from the stream first, hence the "back" in "putback". If you want to insert characters into the cin, this thread will provide the answer:
Injecting string to 'cin'
What must have happened is that your putback didn't find any room in the streambuf get area associated with std::cin (otherwise a read position would have been available and egptr() - gptr() would have been non-zero) and must have gone to an underlying layer thanks to pbackfail.
in_avail() will call showmanyc() and zero (which is the default implementation of this virtual function) is a safe thing to return as it means that a read might block and it might fail but isn't guaranteed to do either. Obviously it is possible for an implementation to provide a more helpful implementation for showmanyc() in this case, but the simple implementation is cheap and conformant.

c++ isalnum endless loop

Greetings!
Lets cut the excessive intro this time and get straight to the point.
I have a problem in C++ using the isalnum method.
the code:
int playAgainst = 0;
do
{
cout << "Who do you want to play against?(1/2)\n";
cout << "1: Human player\n";
cout << "2: Computer player\n";
cin >> playAgainst
} while(!isalnum(playAgainst) && playAgainst != 0);
As seen in the code, I'm providing the user with a choice. Play against human or play against a computer.
What I want is, as long as the user enters anything else then an integer value(cin >> playAgainst) to repeat the question. However, If i enter a char, or string value, it keeps looping endlessly. I am not 100% sure, but it would be obvious, if the problem is, that the non int value is already saved as the value for playAgainst.. How can I check in this bit of code if the input value is int before saving it?
Or is the only possibility to save as a char/string and then check?
If the latter is the case, a new problem arises. isalnum only accepts int as parameter, atleast from what I know. How will I check if that string or char is an int?
Thank you for taking the time to read. And hopefully Ill be accepting a reply as answer soon ^^
Thanks everyone for the answers.
I have gotten what I wanted, and everything has been solved.
The reason I chose for the accepted answer, is well... because initially, it made my code work the way I want it to. I want to accept multiple answers though..
Make playAgainst a char and compare against '0', not 0. Right now, the user has to enter the ASCII (or whatever your character set is) code for the character '1' or '2'.
isalnum won't work on ints outside the valid range of char, except for EOF. (The fact that it takes an int argument is a leftover from C, which has different integer promotions rules than C++. to accomodate for EOF.)
Remove the isalnum() check. cin >> playAgainst will convert anything except a number to zero, which will be caught by the second check. Note that this is only an option because zero is not a valid input.
isalnum() is useful if you're interpreting the characters yourself, but in this case the stream has already done that for you.
This is how the compiler will implement isalnum:
int isalnum (int ch)
{
return (ch >= 'a' && ch <= 'z') ||
(ch >= 'A' && ch <= 'Z') ||
(ch >= '0' && ch <= '9');
}
So you might as well write that code snippet in your own code, and it will be equivalent with an inlined version of isalnum.
It's because you don't clear the buffer. When the input is invalid, you need to clear it from the buffer, and then you can move on to the next input, else you're trying to extract the same input every time (which fails, because it's the same bad input), and thus enter an infinite loop.
The problem is that you're inputing an int, and not a char. And if the
text in the input isn't an int, then the input fails. In which case,
playAgainst isn't modified, and the failure is memorized in std::cin
until you explicitly clear the error. And inputting from a stream in an
error state is a no-op. What you probably want to do is
Input a single character: if you don't want to skip spaces, using
`std::cin.get( ch )` or `ch = std::cin.get()`. (In the latter
case, `ch` should be an `int`, since it must also handle `EOF`.
On the other hand, you can use `::isalnum` on it directly, which
you can't do if `ch` is a `char`.
Fully check for valid input: not just `::isalnum`, but rather
whether the input is a legal selector in your list. Something
along the lines of:
ch != EOF && std::find( legalChars.begin(), legalChars.end(), (char)ch ) != legalChars.end()
In case of error, clear any remaining input, say with:
std::cin.ignore(INT_MAX, '\n');
In practice, you'll probably want to treat EOF differently from
an erroneous command. (If you don't clear the input after EOF, you
won't be able to read anything else. But presumably, if you got EOF,
it's because the user gave up, and doesn't want to try any more.)
Finally, it's probably preferrable to keep all of the information in
a common location, using a table of:
struct Command
{
char op;
char const* prompt;
void (* func)();
};
You then loop over a table of these to output the prompt, search it to
see if the character was legal, and finally, call the function on the
entry you found. Or define an abstract base class, a concrete class
deriving from it for each command, and use an std::map<char,
AbstractBase*> for the mapping, etc. Very C++, but perhaps a bit
overkill for such a simple case.
Why not use isdigit().