Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I write to cin, the input stream, in C++

Tags:

c++

io

input

So I have a program (a game) designed to take input from a human via a keyboard. It is desirable, however, that at certain points I take control away from the user and make certain decisions for them. While it would be possible to write special-case code for use when events force the effects of user input to be emulated, I would much prefer to override the input stream (cin in this case) so that the program is in fact responding no different to forced decisions than had the user made such a decision of their own free will.

I have tried writing to it like I would an output stream (cin<<'z' for example) but the << operator isn't defined for cin and I don't know how to define it.

Would it be better to write to the keyboard buffer? If so, how would I do that in a system agnostic manner?

like image 811
Lurker Avatar asked Oct 17 '25 16:10

Lurker


2 Answers

Writing to the input is quite a hack. It would be much cleaner design to put an abstraction layer between the actual input (like cin) and the game acting on that input. Then, you could just reconfigure this abstraction layer to respond to procedurally generated commands instead of to cin whenever necessary.

like image 148
Angew is no longer proud of SO Avatar answered Oct 19 '25 07:10

Angew is no longer proud of SO


You can insert a streambuf into std::cin, something like:

class InjectedData : public std::streambuf
{
    std::istream* myOwner;
    std::streambuf* mySavedStreambuf;
    std::string myData;
public:
    InjectedData( std::istream& stream, std::string const& data )
        : myOwner( &stream )
        , mySavedStreambuf( stream.rdbuf() )
        , myData( data )
    {
        setg( myData.data(), myData.data(), myData.data() + myData.size() );
    }
    ~InjectedData()
    {
        myOwner->rdbuf(mySavedStreambuf);
    }
    int underflow() override
    {
        myOwner->rdbuf(mySavedStreambuf);
        return mySavedStreambuf->sgetc();
    }
};

(I've not tested this, so there may be errors. But the basic principle should work.)

Constructing an instance of this with std::cin as argument will return characters from data until the instance is destructed, or all of the characters have been consumed.

like image 30
James Kanze Avatar answered Oct 19 '25 06:10

James Kanze



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!