Efficient way to implement a bounded string formatting operator for use with <<?

给你一囗甜甜゛ 提交于 2019-12-22 10:23:10

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!