Frage

Gibt es trotzdem eine bekannte Anzahl von Bytes zu lesen, direkt in eine std :: string, ohne einen temporären Puffer zu schaffen, dies zu tun?

zB zur Zeit kann ich es tun, indem

boost::uint16_t len;
is.read((char*)&len, 2);
char *tmpStr = new char[len];
is.read(tmpStr, len);
std::string str(tmpStr, len);
delete[] tmpStr;
War es hilfreich?

Lösung

std::string hat eine resize Funktion, die Sie könnten, oder einen Konstruktor verwenden, die das gleiche tun werden:

boost::uint16_t len;
is.read((char*)&len, 2);

std::string str(len, '\0');
is.read(&str[0], len);

Dies ist nicht getestet, und ich weiß nicht, ob Strings zusammenhängende Speicher hat beauftragt ist.

Andere Tipps

Sie können eine Kombination aus copy_n verwenden und eine insert_iterator

void test_1816319()
{
    static char const* fname = "test_1816319.bin";
    std::ofstream ofs(fname, std::ios::binary);
    ofs.write("\x2\x0", 2);
    ofs.write("ab", 2);
    ofs.close();

    std::ifstream ifs(fname, std::ios::binary);
    std::string s;
    size_t n = 0;
    ifs.read((char*)&n, 2);
    std::istream_iterator<char> isi(ifs), isiend;
    std::copy_n(isi, n, std::insert_iterator<std::string>(s, s.begin()));
    ifs.close();
    _unlink(fname);

    std::cout << s << std::endl;
}

kein Kopieren, keine Hacks, keine Möglichkeit der Überschreitung, kein undefiniertes Verhalten.

Sie könnte so etwas wie getline verwenden:

#include <iostream>
#include <string>
using namespace std;

int main () {
  string str;
  getline (cin,str,' ');
}

würde ich einen Vektor als Puffer verwenden.

boost::uint16_t len;
is.read((char*)&len, 2); // Note if this file was saved from a different architecture 
                         // then endianness of these two bytes may be reversed.

std::vector buffer(len);  // uninitialized.
is.read(&buffer[0], len);

std::string  str(buffer.begin(),buffer.end());

Auch wenn Sie wahrscheinlich mit der Verwendung einer Zeichenfolge als Puffer weg (wie durch GMan beschrieben). Es ist nicht von der Norm gewährleistet, dass ein Strings Mitglieder in aufeinander folgenden Positionen sind (so Ihre aktuelle Implementierung überprüfen und einen großen Kommentar setzen, dass sie die Überprüfung muss, wenn auf einen anderen Compiler / Plattform portieren).

optimieren Sie nur Codelänge oder versuchen, sich eine Kopie hier zu retten? Was ist los mit dem temporären Puffer?

Ich würde argumentieren, dass Sie tatsächlich den Schutz, der Zeichenfolge zu umgehen versuchen, direkt das so tun zu schreiben. Wenn Sie zu einem std :: string besorgt über die Leistung der Kopie sind, weil Sie erkannt haben, dass es in irgendeiner Art und Weise ist die Leistung Ihrer Anwendung zu beeinflussen, werde ich arbeitet direkt mit dem char *.

EDIT: Mehr tun aussehendes ... Initialisierung std :: string von char * ohne Kopie

In der zweiten Antwort, es ist ziemlich flach festgestellt, dass Sie nicht erreichen können, was Sie suchen (dh. Bevölkern eine std :: string ohne Iteration über die char * zu kopieren.) Erreichen

Werfen Sie einen Blick auf Ihre Last-Routine (es hier posten vielleicht?) Und minimieren Zuweisungen: neue und löschen Sie sicherlich nicht frei, so kann man zumindest etwas Zeit sparen, wenn Sie zu den Puffer nicht ständig neu erstellen . Ich finde es immer hilfreich Lösch es durch memset'ing den Puffer auf 0 oder null dem ersten Index des Arrays jede Iteration beendet, aber Sie können schnell, dass Code im Interesse der Leistung beseitigen, wenn Sie in Ihrem Algorithmus sicher sind.

Eine einfache Möglichkeit wäre:

std::istream& data
const size_t dataSize(static_cast<size_t>(data.rdbuf()->in_avail()));
std::string content;
content.reserve( dataSize);
data.read(&content[0], dataSize);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top