3

Is it possible in C++ to redirect stdin to string in C++?

Using freopen I can redirect stdin to file, so both scanf and cin will use a content of that file. Using manipulations with stringstream and cin.rdbuf() I can redirect cin to that string, so any call to cin will work with my string. BUT scanf will continue to work with previous input stream. I guess it is possible to do with Unix's pipes but it's not available under Windows.

Is it possible to solve this in a portable way?

flashnik
  • 1,900
  • 4
  • 19
  • 38
  • Pipes work in Windows too, but you need to run a secondary executable. – Mats Petersson May 08 '13 at 14:57
  • What's wrong with using a file? Write your string to a temporary file and redirect `stdin` to it. – jxh May 08 '13 at 15:00
  • Well, it's not a way for me. I need to make a temporery redirect during application work, possibly several times. – flashnik May 08 '13 at 15:00
  • @user315052, the wish to prefetch data in memory. – flashnik May 08 '13 at 15:01
  • @flashnik: Perhaps you should consider using `sscanf()` instead then. You should consider using `sscanf()` instead of `scanf()` anyway. – jxh May 08 '13 at 15:07
  • The problem is that real IO happens in the code I don't control, in something like an extension. – flashnik May 08 '13 at 15:14
  • Ok, perhaps a silly question, but why do you need to use `stdin` to take data from a string? Seems like a saner method, assuming you have something that reads from either `stdin` or a string, to write a function that reads a string from `stdin` (assuming `fgets` or similar isn't good enough) and then pass that to a function that takes a string argument. – Mats Petersson May 08 '13 at 15:15
  • @flashnik: When you said *the wish to prefetch data in memory*, it led me to believe you are controlling the whole system. Since you do not, I would concentrate on getting a correct working system first with files. You can optimize that with a RAM disk, [but it probably would not be needed](http://stackoverflow.com/questions/909869/in-memory-file-system-for-windows). – jxh May 08 '13 at 15:29

2 Answers2

1

Assuming both the C and C++ standard streams are synchronized, the following should work:

class save_buffer
{
public:
    save_buffer(std::ios& str) :
        my_str(str),
        m_sbuf(str.rdbuf())
    { }

    ~save_buffer()
    {
        m_str.rdbuf(m_sbuf);
    }
private:
    std::ios& m_str;
    std::streambuf* m_sbuf;
};

int main()
{
    std::istringstream buf;

    save_buffer sb(std::cin);
    std::cin.rdbuf(buf.rdbuf());
}
David G
  • 94,763
  • 41
  • 167
  • 253
0

This isn't the best way to do it, but you can make it work with something like this:

// warning - has side effects (sets noskipws) but we don't care (its an example)
ostream& operator<< (ostream& out, istream& in)
{
    in >> noskipws;
    char c;
    in >> c;

    while (in)
    {
        out << c;
        in >> c;
    }

    return out;
}

int main()
{
    ostringstream inputstr;
    inputstr << cin;

    inputstr.str(); // contains all data from stdin
    return;
}
Wug
  • 12,956
  • 4
  • 34
  • 54
  • I'm also aware that pulling data out of the stream one character at a time is probably suboptimal too. This solution is unpolished for a number of reasons. – Wug May 08 '13 at 15:54