2010-04-01 18 views
22

Si paso una char * en una función. Quiero entonces tomar ese char * convertirlo a std :: string y una vez que obtengo mi resultado convertirlo de nuevo a char * desde std :: string para mostrar el resultado.cómo copiar char * en una cadena y viceversa

  1. No sé cómo hacer esto para la conversión (no estoy hablando const char *, pero sólo char *)
  2. No estoy seguro de cómo manipular el valor del puntero que envío en.

así los pasos que tengo que hacer

  1. toma en un char *
  2. convertirlo en una cadena.
  3. tome el resultado de esa cadena y vuelva a colocarla en forma de un carácter *
  4. devuelva el resultado de manera que el valor esté disponible fuera de la función y no se destruya.

Si es posible, puedo ver cómo se puede hacer a través de la referencia contra un puntero (cuya dirección paso por valor pero puedo modificar el valor al que apunta el puntero) aunque la copia del puntero dirección en la función se destruye todavía veo el valor cambiado fuera

gracias

+1

"conviértalo de nuevo a char * desde std :: string para mostrar el resultado". - ¿Por qué no puedes mostrar el resultado cuando es una cadena? Debería poder hacer std :: cout << my_string; –

+0

esta es una interfaz con la que tengo que trabajar. entonces, aunque uso string siempre que puedo si una interfaz requiere char *, eso es lo que tengo que usar. el parámetro de salida de función es un char * ... y eso es con lo que tengo que trabajar con – user295030

+3

En ese caso, la interfaz debería decir algo acerca de la gestión de memoria. Digo "debería" porque * podría * no - algunas interfaces están mal especificadas, hecho de la vida. Siempre que devuelva un puntero desde una función, debe indicar quién es responsable de asignar los datos que se indican, cuánto tiempo permanece válido y quién es responsable de liberarlo (si corresponde). Si puede resolverlo, puede averiguar cómo devolver un valor de puntero apropiado. –

Respuesta

36

Conversión de un char* a un std::string:.!

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

Conversión de un std::string a 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; 

Yo prefiero usar un std::vector<char> en lugar de un verdadero char*; entonces usted no tiene que manejar su propia 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í, pero en el último caso cuando usa c_str() devuelve un const char * not a char * – user295030

+0

@ user295030: 'c_str()' devuelve un 'const char *'; el segundo parámetro para 'strcpy' (la cadena fuente) es de tipo' const char * '. Si solo necesita 'const char *', entonces no hay necesidad de hacer esto, y solo puede usar el resultado de 'c_str()'. –

+0

s.c_str() devuelve un const char *, que es la razón por la que está copiando en el char * llamado c. En su función, usted devolvería c. –

1

Es necesario tener cuidado de cómo manejar la memoria del puntero regrese, por ejemplo, el siguiente código no funcionará porque la memoria asignada en el std: : cadena se lanzará cuando fn() sale.

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

Una solución consiste en asignar la memoria en la función y asegúrese de que la persona que llama de la función libera:

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 

Alternativamente, si usted conoce un límite superior en el tamaño de la cadena que puede crearlo usted mismo en la pila y pasar un puntero, por ej.

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

Puede mantener un recolector de basura para su biblioteca implementada como std::vector<char*> g_gc; que es accesible en la biblioteca 'lib'.Más tarde, se puede liberar a todos los punteros en g_gc a su conveniencia llamando 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; 
} 

función release_garbage se verá así:

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

En un modelo único de rosca, se puede mantener esta g_gc estática. El modelo de subprocesos múltiples implicaría bloquearlo/desbloquearlo.

+0

Esto es _muy_ peligroso; almacenar punteros descubiertos en un contenedor casi siempre es una mala idea, porque es muy difícil garantizar la seguridad de las excepciones. (Consulte aquí las alternativas: http://stackoverflow.com/questions/2558134/2558152#2558152). Además, el código en su respuesta tiene un error crítico: usa '' no coincidente '' nuevo [] 'y' eliminar'. –

+0

que es un gran hilo. Gracias por señalar sobre eliminar []. – Pankaj

+0

Y con esto no puedes incluso "recolectar basura" a pedido porque algunos punteros podrían estar en uso. Solo puede hacerlo de forma segura cuando se cierra la aplicación, lo que lo hace inútil ya que la memoria asignada se libera cuando la aplicación sale de todos modos. – Blindy

Cuestiones relacionadas