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 thestrarray (which FYI, you don't actually need, as you could just copy characters from thetempstring directly intoresinstead), you can justdelete[]it before exiting. But forres, themembufwould have to hold on to that pointer anddelete[]it when themembufitself is no longer being used.But, more importantly, your use of
membufis simply wrong. You are creating it as a local variable ofskipchar(), so it will be destroyed whenskipchar()exits, leaving thestreamwith a dangling pointer to an invalid object. Thestreambuf*pointer you assign to thestreammust remain valid for the entire duration that it is assigned to theistream, which means creating themembufobject withnew, and then the caller will have to remember to manuallydeleteit at a later time (which kind of defeats the purpose of usingoperator>>). However, a stream manipulator really should not change therdbufthat thestreamis pointing at in the first place, since there is not a good way to restore the previousstreambufafter 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
streambufto thestream, thus affecting all subsequentoperator>>calls. Instead, make a manipulator that takes a reference to the output variable, and then reads from thestreamand outputs only what is needed (similar to how standard manipulators likestd::quotedandstd::get_timework), eg:Online Demo
Alternatively:
Online Demo