Эффективный способ реализовать оператор форматирования ограниченной строки для использования с <<? - PullRequest
3 голосов
/ 16 октября 2011

Я ищу что-то, где:

string pearString ("pear");
string bananaString ("banana");

cout << ???? 5 ??? pearString ??????? << "[end]" << endl;
cout << ???? 5 ??? bananaString ??????? << "[end]" << endl;

Будет (для некоторой последовательности символов кода ???) выводить:

pear[end]
banan[end]

Но я бы хотел, чтобыработать без необходимости выполнять операцию подстроки, которая будет копировать строку.Если я что-то упустил, для этого нет спецификатора форматирования.(Спецификатор setw добавляет более короткие строки, но допускает переполнение более длинных строк.)

"хитрая" вещь, о которой я подумал, - создать легкий класс-обертку с собственным оператором вывода потока,Он взял бы (неконстантную) строковую ссылку и предел в своей структуре.Затем оператор вывода будет проверять длину, делать стандартный вывод, если он меньше или равен пределу.Если бы он был больше, он временно вставил бы нулевой символ в позицию длины, достаточно длинную, чтобы сделать вывод ..., а затем вернул исходный символ обратно.

( UPDATE: на самом деле эта идея не сработала бы, поскольку << игнорирует встроенные нули.)

В любом случае идея о том, как она будет выглядеть, будет:

cout << strlimiter(5, pearString) << "[end]" << endl;
cout << strlimiter(5, bananaString) << "[end]" << endl;

Какие-нибудь более чистые решения, которые будут работать с константными строками и не будут выводить данные из-под вас?Что-то, что использует другие хуки или приемы расширения iostream?Это где-то покрыто библиотекой?


ОБНОВЛЕНИЕ : я пропустил метод iostream write вместо <<, поэтомуВот пример кода:

#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;
}

Есть еще хитрость, которая может сделать это даже на меньше стоимости во время выполнения?

Ответы [ 2 ]

2 голосов
/ 16 октября 2011

Почему бы просто не использовать write функцию члена ostream:

cout.write(bananaString.c_str(),5);

Возможно, что удивительно, вы даже можете поместить это в начало цепочки вставки. Взяв за основу ваш пример, вы можете использовать следующую несколько запутанную цепочку:

cout.write(bananaString.c_str(),5) << "[end]" << endl;
2 голосов
/ 16 октября 2011

Для вашего класса-оболочки в перегруженном operator<< вместо использования << в строке используйте функцию ostream::write.

the_stream.write(the_string.c_str(), the_size);
...