I've seen examples that allow you to create a manipulator that inserts delimiters but none of those manipulators are sticky. That is, the manipulator returns a special class that inserts the delimiter, rather than modifying the output stream permanently so that it can do it on its own.
I want to be able to do this:
std::cout << sep(", ");
std::cout << "hello" << "world";
// "hello, world"
At the moment this prints "h, e, l, l, o, w, o, r, l, d" when I need it to be "hello, world". The reason I'm getting the wrong output is because I put the printing in the overflow() method and overflow() is being called for each character. I'm not sure where is the appropriate place to put it.
Sorry about it being verbose. If I knew a simpler way to write it I would. Just start from the bottom and work your way up:
#include <iostream>
#include
// index for delimiter
int separator() {
static int idx = std::ios_base::xalloc();
return idx;
}
// index for storage of dynamically-allocated buffer
int rdbuffer() {
static int idx = std::ios_base::xalloc();
return idx;
}
struct custom_separator : std::streambuf {
public:
custom_separator(std::ostream& _stream)
: stream(_stream), buffer(_stream.rdbuf()) {}
int_type overflow(int_type c) {
// has a token been read already
if (token_read) {
char* delim = static_cast(stream.pword(separator()));
// print delim
buffer->sputn(delim, strlen(delim));
}
token_read = true;
return buffer->sputc(c);
}
private:
std::ostream& stream;
std::streambuf* buffer;
bool token_read = false;
};
// deletes the buffer and the delimiter
void cleanup(std::ios_base::event evt, std::ios_base& str, int idx) {
if (evt == std::ios_base::erase_event) {
delete static_cast(str.pword(idx));
delete static_cast(str.pword(rdbuffer()));
}
}
std::ostream& set_separator(std::ostream& os, const char* str) {
if (!os.bad()) {
// If a separator string doesn't exist, assign os a buffer that prints one
if (!os.pword(separator())) {
auto buf = new custom_separator(os);
os.rdbuf(buf);
// this is to keep track of buf so we can delete it later
os.pword(rdbuffer()) = static_cast(buf);
os.register_callback(cleanup, separator());
}
// delete the previous separator
delete static_cast(os.pword(separator()));
// store the new one
os.pword(separator()) = (void*)(str);
}
return os;
}
struct sep {
explicit sep(const char* _sep)
: separator(new char[strlen(_sep) + 1]) {
strcpy(separator, _sep);
}
sep(const sep&) = delete;
sep(const sep&&) = delete;
char* separator;
};
std::ostream& operator<<(std::ostream& os, const sep& manip) {
set_separator(os, manip.separator);
return os;
}
int main() {
std::cout << sep(", ");
std::cout << "hello";
std::cout << "world";
// "h, e, l, l, o, w, o, r, l, d"
}
The main issue with overflow() is that I don't know when to detect when the end of a token like "hello" has been read to know when to insert.
JavaScript questions and answers, JavaScript questions pdf, JavaScript question bank, JavaScript questions and answers pdf, mcq on JavaScript pdf, JavaScript questions and solutions, JavaScript mcq Test , Interview JavaScript questions, JavaScript Questions for Interview, JavaScript MCQ (Multiple Choice Questions)