I need to make a custom istream manipulator that reads 5 characters from input, then skip 5 characters from input, and does it to the end of the string. Example:
string line;
cin >> skipchar >> line;
This is that I did, but it doesn't work for some reason. Also, it would be better, if I don't use <sstream>
struct membuf : streambuf
{
membuf(char* begin, char* end) {
this->setg(begin, begin, end);
}
};
istream& skipchar(istream& stream)
{
string temp;
getline(stream, temp);
char *str = new char[temp.size() + 1];
strcpy(str, temp.c_str());//get string and convert to char*
char* res = new char[strlen(str)];
for (int i=0,j=0;i<strlen(str);i++)
if ((i / 5) % 2 == 0) //get first 5, then 5 skip, etc
res[j++] = str[i];
membuf b(res, res + strlen(res)); //copy str to buffer
stream.rdbuf(&b);
return stream;
}
int main()
{
string str;
cout << "enter smth:\n";
cin >> skipchar >> str;
cout << "entered string: " << str;
return 0;
}
You did not show your input, but I don't think
getline()
would be appropriate to use in this situation.operator>>
is meant to read a single word, not a whole line.In any case, you are leaking both
char[]
arrays that you allocate. You need todelete[]
them when you are done using them. For thestr
array (which FYI, you don't actually need, as you could just copy characters from thetemp
string directly intores
instead), you can justdelete[]
it before exiting. But forres
, themembuf
would have to hold on to that pointer anddelete[]
it when themembuf
itself is no longer being used.But, more importantly, your use of
membuf
is simply wrong. You are creating it as a local variable ofskipchar()
, so it will be destroyed whenskipchar()
exits, leaving thestream
with a dangling pointer to an invalid object. Thestreambuf*
pointer you assign to thestream
must remain valid for the entire duration that it is assigned to theistream
, which means creating themembuf
object withnew
, and then the caller will have to remember to manuallydelete
it at a later time (which kind of defeats the purpose of usingoperator>>
). However, a stream manipulator really should not change therdbuf
that thestream
is pointing at in the first place, since there is not a good way to restore the previousstreambuf
after subsequent read operations are finished (unless you define another manipulator to handle that, iecin >> skipchar >> str >> stopskipchar;
).In this situation, I would suggest a different approach. Don't make a stream manipulator that assigns a new
streambuf
to thestream
, thus affecting all subsequentoperator>>
calls. Instead, make a manipulator that takes a reference to the output variable, and then reads from thestream
and outputs only what is needed (similar to how standard manipulators likestd::quoted
andstd::get_time
work), eg:Online Demo
Alternatively:
Online Demo