tags:

views:

35

answers:

1

As an exercise, I'm trying to create a input stream manipulator that will suck up characters and put them in a string until it encounters a specific character or until it reaches eof. The idea came from Bruce Eckel's 'Thinking in c++' page 249.

Here's the code I have so far:

#include <string>
#include <iostream>
#include <istream>
#include <sstream>
#include <fstream>
#include <iomanip>
using namespace std;

class siu 
{
    char T;
    string *S;
public:

    siu (string *s, char t)
    {
        T = t;
        S = s;
        *S = "";
    }


    friend istream& operator>>(istream& is, siu& SIU)
    {
        char N;
        bool done=false;
        while (!done)
        {
            is >> N;
            if ((N == SIU.T) || is.eof())
                done = true;
            else
                SIU.S->append(&N);
        }
        return is;
    }
};

and to test it....

        {
            istringstream iss("1 2 now is the time for all/");
            int a,b;
            string stuff, zork;

            iss >> a >> b >> siu(&stuff,'/');
            zork = stuff;
        }

the idea being that siu(&stuff,'/') will suck up characters from iss until it encounters the /. I can watch it with the debugger as it gets the characters 'n' 'o' 'w' through '/' and terminates the loop. It all seems to be going swimingly until I look at Stuff. Stuff has the characters now etc BUT there are 6 extra characters between each of them. Here's a sample:

  • &stuff 0x0012fba4 {0x008c1861 "nÌÌÌýoÌÌÌýwÌÌÌýiÌÌÌýsÌÌÌýtÌÌÌýhÌÌÌýeÌÌÌýtÌÌÌýiÌÌÌýmÌÌÌýeÌÌÌýfÌÌÌýoÌÌÌýrÌÌÌýaÌÌÌýlÌÌÌýlÌÌÌý"}

What's going on?

+3  A: 

This line:

SIU.S->append(&N);

appends the character as a char *. The append function is expecting a null terminated string, so it keeps reading from &N, (&N)+1... until it sees a zero byte.

You can either make up a small null terminated char array and pass that in, or you can use the an alternate append function that takes a count and a character to append:

SIU.S->append(1, N);
The Dark
Thanks! So close but no cigar. I changed it to SIU.S->append( with N = is.get(). Seems to works as I hoped now.
Mike D
even simpler: while (is >> n) siu.s += n; Note: all-uppercase identifiers are - by convention - reserved for preprocessor defines... using them can lead to bugs that are very hard to track down. (though strangely, single letter ones ala template <class T>, U etc. is common pracice)
Tony
@Tony: Nothing that doesn't begin with an underscore is reserved by the language for anything. Any good style guide includes that rule, though.
Potatoswatter
Ok, this all gets me thinking about why either the iostream member function getline or the string member function getline can't be used in place of siu above. They have similar definition except for the operator business. Just thinking out loud. Seems like you need something like I did to define a temporary instance which you can't do with a function. Should be able to use either in the definition of siu operator >> though.
Mike D
@tony: S is a pointer to a string so I need *siu.S +=N; I wanted to stop at but not store the terminator so I changed the while to "while (!is.eof())" eliminated the done crud, and added a break when the terminator was encountered.
Mike D
It seems this would be a valuable tool for parsing input. One could embed any algorithm you wanted and even backup using put().
Mike D