2010-01-13 11 views
7

Esistono numerose funzioni Win32 che prendono l'indirizzo di un buffer, ad esempio TCHAR[256] e scrivono alcuni dati su quel buffer. Potrebbe essere inferiore alla dimensione del buffer o potrebbe essere l'intero buffer.Come mescolare std :: string con le funzioni Win32 che accettano i buffer char []?

Spesso si chiama questo in un ciclo, ad esempio per leggere i dati da un flusso o un tubo. Alla fine vorrei restituire in modo efficiente una stringa che ha i dati completi di tutte le chiamate iterate per recuperare questi dati. Stavo pensando di usare std::string poiché + = è ottimizzato in modo simile ai metodi StringBuffer.append()/StringBuilder.Append() di Java o C#, favorendo la velocità anziché la memoria.

Ma non sono sicuro del modo migliore per combinare lo std::string con le funzioni Win32, poiché queste funzioni richiedono il char[] per iniziare. Eventuali suggerimenti?

risposta

6

std::string ha una funzione che restituisce c_str() suo equivalente stringa di C-stile. (const char *)

Inoltre, std::string ha sovraccaricato l'operatore di assegnazione che accetta una stringa in stile C come input.

ad es. Cerchiamo ss essere std::string istanza e sc essere una stringa in stile C allora l'interconversione può essere eseguita come:

ss = sc; // from C-style string to std::string 
sc = ss.c_str(); // from std::string to C-style string 

UPDATE:

Come Mike Weller ha sottolineato, se UNICODE macro viene definita, quindi la le stringhe saranno wchar_t* e quindi dovresti usare std::wstring invece.

+1

Si noti inoltre che TCHAR cambierà in base al valore della macro UNICODE. Se UNICODE è definito, le stringhe saranno wchar_t * e dovresti invece usare std :: wstring. –

+1

scrivere direttamente su un buffer interno 'std :: string' può essere pericoloso, poiché la stringa memorizza anche cose come la lunghezza che potrebbe non essere valida se si esegue questa operazione. –

+0

Idan è corretto. Non utilizzare std :: string per una funzione che scriverà nel buffer delle stringhe. – jmucchiello

6

Invece di std :: string, suggerisco di utilizzare std::vector e di utilizzare &v.front() mentre si utilizza v.size(). Assicurati di avere lo spazio già allocato!

È necessario fare attenzione con std::string e dati binari.

s += buf;//will treat buf as a null terminated string 
s += std::string(buf, size);//would work 
+1

sarebbe probabilmente consigliabile impostare una dimensione iniziale per il vettore nel ctor, o in alternativa chiamare 'resize()' su di esso. poi passa 'size()' come lunghezza del buffer. –

+0

@ Mike Weller: Grazie per il voto negativo ... Non vedo quale sia il tuo punto di vista qui ... che ne dici di .data()? Naturalmente so cosa fa .c_str(), ma l'OP dice che le funzioni contengono un buffer e, per dati binari arbitrari, è meglio usare std :: vector piuttosto che std :: string. –

+0

Si noti che è necessario creare il vettore con il costruttore della dimensione o richiamare ridimensiona() su di esso. –

11

Se l'argomento è ingresso sola uso std::string simili

std::string text("Hello"); 
w32function(text.c_str()); 

Se l'argomento è ingresso/uscita uso std::vector<char> invece simili:

std::string input("input"); 
std::vector<char> input_vec(input.begin(), input.end()); 
input_vec.push_back('\0'); 
w32function(&input_vec[0], input_vec.size()); 
// Now, if you want std::string again, just make one from that vector: 
std::string output(&input_vec[0]); 

Se l'argomento è solo output utilizzare anche std::vector<Type> come questo:

// allocates _at least_ 1k and sets those to 0 
std::vector<unsigned char> buffer(1024, 0); 
w32function(&buffer[0], buffer.size()); 
// use 'buffer' vector now as you see fit 

È anche possibile utilizzare std::basic_string<TCHAR> e std::vector<TCHAR> se necessario.

Puoi leggere di più sull'argomento nel libro Efficace STL di Scott Meyers.

2
  • È necessario un tipo di stringa compatibile: typedef std::basic_string<TCHAR> tstring; è una buona scelta.

  • Per gli argomenti di input only, è possibile utilizzare il metodo .c_str().

  • Per buffer, la scelta è leggermente meno chiara:

std :: basic_string non è garantito utilizzare memorizzazione contiguo come std :: vector è. Tuttavia, tutte le implementazioni std :: basic_string che ho visto utilizzano storage contiguo e il comitato per gli standard C++ considera la garanzia mancante come difetto dello standard. Il difetto è stato corretto nella bozza C++ 0x.

Se siete disposti a piegare le regole sempre leggermente - senza conseguenze negative - è possibile utilizzare & (* aString.begin()) come un puntatore a un buffer TCHAR di lunghezza aString.size(). Altrimenti sei bloccato con std :: vector per ora.

Ecco cosa comitato di serie C++ hanno da dire su di stoccaggio stringa contigue:

Non standardizzazione questo esistente pratica non dà implementatori più libertà. Abbiamo pensato che potrebbe essere una decadi . Ma i venditori hanno parlato con le loro implementazioni e con la loro voce alle riunioni del GAL. Le implementazioni saranno contigue , indipendentemente dallo standard . Quindi lo standard potrebbe anche dare ai client stringa più design scelte.

Problemi correlati