3 Stimmen

Effizienter Weg zur Implementierung eines begrenzten String-Formatierungsoperators zur Verwendung mit <<?

Ich bin auf der Suche nach etwas, wo:

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

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

Wird (für eine bestimmte Folge von Codezeichen ???) ausgegeben:

pear[end]
banan[end]

Aber ich möchte, dass dies zu arbeiten, ohne eine Teilzeichenfolge-Operation, die die Zeichenfolge kopieren würde zu tun. Wenn ich nicht etwas übersehe, gibt es keine Formatierung Spezifizierer für diese. (Die setw Spezifizierer füllt kürzere Zeichenketten auf, lässt aber längere Zeichenketten überlaufen).

Eine "knifflige" Sache, an die ich gedacht habe, wäre, eine leichtgewichtige Wrapper-Klasse mit einem eigenen Stream-Operator zu erstellen. Es würde die (non-const) String-Referenz und eine Grenze in seiner Struktur nehmen. Dann würde der Ausgabeoperator die Länge testen und eine Standardausgabe machen, wenn sie kleiner oder gleich dem Limit ist. Wenn sie größer war, würde er vorübergehend ein Null-Zeichen an der Längenposition einfügen, gerade lange genug, um die Ausgabe zu machen ... und dann das ursprüngliche Zeichen wieder einfügen.

( UPDATE: Eigentlich hätte diese Idee nicht so gut funktioniert << ignoriert eingebettete Nullen).

Wie auch immer, die Idee, wie es aussehen würde, wäre folgende:

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

Irgendwelche saubereren Lösungen, die bei Konstanten funktionieren würden und die Daten nicht unter Ihnen wegfummeln würden? Etwas, das andere Hooks oder Tricks der Erweiterung iostream verwendet? Wird dies irgendwo durch eine Bibliothek abgedeckt?


アップデイト : Ich hatte das übersehen write Methode von iostream anstelle von << Hier ist also ein Beispielcode:

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

Noch mehr Tricks, die es noch schwieriger machen könnten weniger der Kosten zur Laufzeit?

2voto

Benjamin Lindley Punkte 99114

Für Ihre Wrapper-Klasse, in der überladenen operator<< anstelle von << auf die Zeichenkette, verwenden Sie die ostream::write Funktion.

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

2voto

Michael Goldshteyn Punkte 68533

Warum verwenden Sie nicht einfach die write Mitgliedsfunktion von ostream :

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

Es mag überraschen, dass Sie dies sogar an den Anfang einer Einfügekette setzen können. Ausgehend von Ihrem Beispiel können Sie die folgende, etwas verschlungene Kette verwenden:

cout.write(bananaString.c_str(),5) << "[end]" << endl;

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X