2010-04-01 12 views
22

Se si passa un char * in una funzione. Voglio quindi prendere quel char * convertirlo in uno std :: string e una volta ottenuto il risultato converti nuovamente in char * da una stringa: std :: per mostrare il risultato.come copiare char * in una stringa e viceversa

  1. non so come fare per la conversione (non sto parlando const char *, ma solo char *)
  2. Non sono sicuro di come manipolare il valore del puntatore mando in.

così passi ho bisogno di fare

  1. prendere in un char *
  2. convertirlo in una stringa.
  3. prendere il risultato di tale stringa e riportarlo sotto forma di char *
  4. restituire il risultato in modo che il valore sia disponibile all'esterno della funzione e non venga distrutto.

Se possibile Posso vedere come potrebbe essere fatto tramite riferimento vs un puntatore (il cui indirizzo passo in termini di valore comunque posso comunque modificare il valore che puntatore sta puntando. Così, anche se la copia del puntatore indirizzo nella funzione viene distrutta continuo a vedere il valore modificato esterno

grazie

+1

"convertirlo di nuovo in char * da una stringa di std :: per mostrare il risultato." - Perché non puoi mostrare il risultato quando si tratta di una stringa? Dovrebbe essere in grado di fare std :: cout << my_string; –

+0

questa è un'interfaccia con cui devo lavorare. quindi sebbene io usi la stringa ogni volta che posso, se un'interfaccia richiede char *, questo è ciò che devo usare. il parametro di output della funzione è un char * ... ed è quello che devo lavorare con – user295030

+3

In questo caso, l'interfaccia dovrebbe dire qualcosa sulla gestione della memoria. Dico "dovrebbe" perché * potrebbe * non - alcune interfacce sono specificate male, fatto della vita. Ogni volta che si restituisce un puntatore da una funzione, è necessario indicare chi è responsabile dell'assegnazione dei dati puntati, per quanto tempo rimane valido e chi è responsabile della sua liberazione (se applicabile). Se riesci a risolverlo, puoi capire come restituire un valore puntatore appropriato. –

risposta

36

Conversione di un char* ad un std::string:.!

char* c = "Hello, world"; 
std::string s(c); 

Conversione di un std::string ad un char*:

std::string s = "Hello, world"; 
char* c = new char[s.length() + 1]; 
strcpy(c, s.c_str()); 

// and then later on, when you are done with the `char*`: 
delete[] c; 

Io preferisco usare un std::vector<char> invece di un vero e proprio char*; allora non c'è bisogno di gestire la propria memoria:

std::string s = "Hello, world"; 
std::vector<char> v(s.begin(), s.end()); 
v.push_back('\0'); // Make sure we are null-terminated 
char* c = &v[0]; 
+1

sì, ma nel secondo caso quando si utilizza c_str() restituisce un const char * non un char * – user295030

+0

@ user295030: 'c_str()' restituisce effettivamente un 'const char *'; il secondo parametro di 'strcpy' (la stringa sorgente) è di tipo' const char * '. Se hai solo bisogno di un 'const char *', allora non c'è bisogno di farlo, e puoi semplicemente usare il risultato di 'c_str()'. –

+0

s.c_str() restituisce un const char *, motivo per cui lo sta copiando nel char * chiamato c. Nella tua funzione, restituiresti c. –

1

Hai bisogno di guardare come gestire la memoria dal puntatore si torna, per esempio il codice qui sotto non funziona perché la memoria allocata nella std: : la stringa verrà rilasciata quando fn() si chiude.

const char* fn(const char*psz) { 
    std::string s(psz); 
    // do something with s 
    return s.c_str(); //BAD 
} 

Una soluzione è quella di allocare la memoria nella funzione e assicurarsi che il chiamante della funzione lo rilascia:

const char* fn(const char*psz) { 
    std::string s(psz); 
    // do something with s 
    char *ret = new char[s.size()]; //memory allocated 
    strcpy(ret, s.c_str()); 
    return ret; 
} 
.... 
const char* p = fn("some text"); 
//do something with p 
delete[] p;// release the array of chars 

In alternativa, se si conosce un limite superiore per la dimensione della stringa puoi crearlo nello stack te stesso e passare un puntatore, ad es

void fn(const char*in size_t bufsize, char* out) { 
    std::string s(psz); 
    // do something with s 
    strcpy_s(out, bufsize, s.c_str()); //strcpy_s is a microsoft specific safe str copy 
} 
.... 
const int BUFSIZE = 100; 
char str[BUFSIZE]; 

fn("some text", BUFSIZE, str); 
//ok to use str (memory gets deleted when it goes out of scope) 
0

È possibile mantenere un garbage collector per la libreria implementato come std::vector<char*> g_gc; che è accessibile nella libreria 'lib'.In seguito, è possibile rilasciare tutti i puntatori in g_gc a vostro piacimento chiamando lib::release_garbage();

char* lib::func(char*pStr) 
{ 
    std::string str(pStr); 
    char *outStr = new char[str.size()+1]; 
    strcpy(outStr, str.c_str()); 
    g_gc.push_back(outStr); // collect garbage 
    return outStr; 
} 

funzione release_garbage sarà simile:

void lib::release_garbage() 
{ 
    for(int i=0;i<g_gc.size();i++) 
    { 
     delete g_gc[i]; 
    } 
    g_gc.clear(); 
} 

In un unico modello filettato, è possibile mantenere questo g_gc statica. Il modello multi-thread implicherebbe il blocco/sblocco.

+0

Questo è _molto_ pericoloso; archiviare puntatori nudi in un contenitore è quasi sempre una cattiva idea, perché è molto difficile garantire un'eccezione di sicurezza. (Vedi qui per le alternative: http://stackoverflow.com/questions/2558134/2558152#2558152). Inoltre, il codice nella tua risposta ha un bug critico: usa "new []" e "delete" non corrispondenti. –

+0

questa è una bella discussione. Grazie per aver segnalato l'eliminazione []. – Pankaj

+0

E con questo non è possibile nemmeno "garbage collection" su richiesta perché alcuni indicatori potrebbero essere in uso. Puoi farlo in modo sicuro solo quando l'applicazione termina, il che lo rende inutile poiché la memoria allocata viene rilasciata quando l'applicazione si chiude comunque. – Blindy

Problemi correlati