问题
I'm looking for something where:
string pearString ("pear");
string bananaString ("banana");
cout << ???? 5 ??? pearString ??????? << "[end]" << endl;
cout << ???? 5 ??? bananaString ??????? << "[end]" << endl;
Will (for some sequence of code characters ???) output:
pear[end]
banan[end]
But I'd like this to work without having to do a substring operation that would copy the string. Unless I'm missing something, there is no formatting specifier for this. (The setw specifier pads shorter strings, but allows longer ones to overflow.)
A "tricky" thing I thought of would be to make a lightweight wrapper class with its own stream output operator. It would take the (non-const) string reference and a limit in its constructure. Then the output operator would test the length, do a standard output if it was less than or equal to the limit. If it was greater, it would temporarily poke a null character in at the length position just long enough to do the output...and then put the original character back.
(UPDATE: actually this idea wouldn't have worked as <<
ignores embedded nulls.)
Anyway the idea for the way it would look would be:
cout << strlimiter(5, pearString) << "[end]" << endl;
cout << strlimiter(5, bananaString) << "[end]" << endl;
Any cleaner solutions that would work on const strings and wouldn't be fiddling the data out from under you? Something that uses other hooks or tricks of extending iostream? Is this covered by a library somewhere?
UPDATE: I'd overlooked the write
method of iostream in lieu of <<
, so here's some sample code:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
class strlimiter
{
friend ostream& operator<< (ostream& os, strlimiter sl);
private:
const string& data;
size_t limit;
public:
strlimiter(const string& data, size_t limit) : data(data), limit(limit) {}
~strlimiter() {}
};
ostream& operator<< (ostream& os, strlimiter sl) {
return os.write(sl.data.c_str(), min(sl.data.length(), sl.limit));
}
int main() {
string pearString ("pear");
string bananaString ("banana");
cout << strlimiter(pearString, 5) << "[end]" << endl;
cout << strlimiter(bananaString, 5) << "[end]" << endl;
return 0;
}
Any more trickery that could make it even less of a cost at runtime?
回答1:
Why not just use the write
member function of ostream
:
cout.write(bananaString.c_str(),5);
Perhaps surprisingly, you can even put this at the start of an insertion chain. Taking your example as a basis, you can use the following somewhat convoluted chain:
cout.write(bananaString.c_str(),5) << "[end]" << endl;
回答2:
For your wrapper class, in the overloaded operator<<
, instead of using <<
on the string, use the ostream::write
function.
the_stream.write(the_string.c_str(), the_size);
来源:https://stackoverflow.com/questions/7781746/efficient-way-to-implement-a-bounded-string-formatting-operator-for-use-with