2015-09-09 4 views
5

Sto leggendo le stringhe da una struttura in un file in cui ogni stringa ha una lunghezza fissa, con padding '\0'. Non sono terminati a zero se la stringa memorizzata richiede l'intera lunghezza.Costruisci std :: string da un massimo di X caratteri, fermandosi al char nullo

Attualmente sto costruendo std::string s su quelli come questo:

// char MyString[1000]; 
std::string stdmystring(MyString, ARRAYSIZE(MyString)); 

Tuttavia, questa copia l'imbottitura, anche. Potrei tagliare la stringa ora, ma c'è un modo elegante e veloce per prevenire la copia in primo luogo?

La velocità è più importante dello spazio, poiché viene eseguito in un ciclo.

+0

È possibile utilizzare lo strnlen POSIX per determinare la dimensione. (Si dovrebbe fare qualcosa del genere, altrimenti string :: size() è sempre la dimensione dell'array) –

+0

Vero, sicuramente un'ottimizzazione. Userò questo se nessuno si presenta come farlo senza un secondo ciclo per determinare la dimensione (che era ciò a cui pensavo ...). –

risposta

2

soluzioni semplici sono:

  1. Basta calcolare la lunghezza corretta prima

    • usare sia strnlen come Dieter suggerito
    • o std::find(MyString,MyString+ARRAYSIZE(MyString),'\0') che IME non è più lentamente

    nota che se la tua stringa si adatta alla cache, lo farò ikely dominano il loop aggiuntivi costano

  2. riserva la dimensione massima della stringa (hai detto spazio era meno importante), e scrive un ciclo aggiungendo caratteri finché non si esaurisce la larghezza o colpite un nul (come copy_until)

  3. in realtà creare una stringa di max-size inizializzato con nuls, strncpy in esso, ed eventualmente cancellare unused nuls se si desidera che la dimensione sia corretta

la seconda opzione utilizza solo un singolo ciclo, mentre la terza usa fittiziamente due (nella stringa ctor, e poi nella copia). Tuttavia, lo push_back di ciascun personaggio sembra più costoso dell'assegnazione semplice del personaggio, quindi non sarei sorpreso se il # 3 fosse più veloce nella realtà. Profilo e vedere!

+0

Almeno in Visual Studio, la costruzione di stringhe da una dimensione nota utilizza memcpy ed è molto più veloce di qualsiasi altra cosa, quindi andrò con il metodo Dieter. –

2

bene se la dimensione non è un problema in un modo potenziale per farlo è quello di creare un vuoto std::string quindi utilizzare reserve() di pre-allocare lo spazio potenzialmente necessario e quindi aggiungere ogni carattere fino ad incontrare '\0'.

std::string stdmystring; 
stdmystring.reserve(MyString_MAX_SIZE) ; 
for(size_t i=0;i<MyString_MAX_SIZE && MyString[i]!='\0';++i); 
stdmystring+=MyString[i]; 

reserve() garanties voi uno di allocazione della memoria in quanto si conosce il max_size e la stringa non potrà mai ottenere più grande di quello.

Le chiamate alla funzione + = operatore saranno probabilmente in linea ma deve comunque verificare che la stringa abbia la capacità necessaria che è uno spreco nel tuo caso. Questo potrebbe essere lo stesso o peggio del semplice uso di strlen per trovare prima la lunghezza esatta della stringa, quindi è necessario testarla.

+0

In seguito dovrò esaminare alcune implementazioni di 'std :: string', ma penso che sia possibile che 'reserve' sia una pessimizzazione qui: potrebbe impedire l'Small String Optimization, che potrebbe essere importante per il caso dell'OP, a seconda della media e della lunghezza della corda. – dyp

+0

Sì, questo è vero ma dipende dalla situazione. La stringa corta deve adattarsi allo spazio utilizzato per dimensione, capacità e puntatore per la stringa lunga insieme alle rispettive dimensioni e alcuni flag bit/bit per distinguere tra stringa breve e lunga. Di solito la capacità della stringa corta è solo un po 'più breve di 3 parole macchina. Se la dimensione media della stringa può rientrare in quella riserva() sarà effettivamente negativa per le prestazioni, ma se ci sono un sacco di stringhe sufficientemente lunghe che non si prenotano per prime può essere anche peggio a causa delle molteplici allocazioni e copie. – Abstraction

0

Penso che il modo più semplice sia quello di sovrallocare l'array interno MyString di un byte, sempre null terminare il byte finale e utilizzare il costruttore di stringhe C di std::string. (Tenete presente che molto probabilmente il vostro processo sarà legato all'I/O sul file, quindi qualunque algoritmo utilizzato dal costruttore di C-string dovrebbe andare bene).

Problemi correlati