<div dir="ltr"><p class="" style="margin-bottom:0.0001pt"><span style="font-family:Arial,sans-serif">Gracias por tus
aclaraciones, lo he modificado como me has comentado =) Simplemente una última
duda, ¿al usar </span><span style="font-size:9.5pt;font-family:Consolas">cin.getline(cad_input,
DEFAULT_CHARS); </span><span style="font-family:Arial,sans-serif">estoy inicializando el puntero </span><span style="font-size:9.5pt;font-family:Consolas">cad_input </span><span style="font-family:Arial,sans-serif">verdad?
¿En este caso no es necesario hacer antes </span><span style="font-size:9.5pt;font-family:Consolas">cad_input[0] = 0;</span><span style="font-family:Arial,sans-serif">?</span></p>

<p class=""><span style="font-family:Arial,sans-serif">Un saludo.</span></p></div><div class="gmail_extra"><br><br><div class="gmail_quote">El 8 de agosto de 2013 17:12, Salvador Pozo <span dir="ltr"><<a href="mailto:salvador@conclase.net" target="_blank">salvador@conclase.net</a>></span> escribió:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">El pasado 2013-08-08 11:41:36, Sergio Torró escribió:<br>
<br>
ST> Muchas gracias Salvador. No sabía que existía un blog de C con Clase!<br>
<br>
Hola:<br>
<br>
Por cierto, me estoy dando cuenta de que le pasa lo mismo a prácticamente todo el mundo. :)<br>
<br>
ST> ...mi intención con esto era simplemente<br>
ST> comprender el manejo de cadenas estilo C (según he leído hay mucho código<br>
ST> heredado y conviene saber del tema).<br>
<br>
Siempre es bueno comprender el manejo de cadenas estándar C. Como bien dices, hay muchísimo código escrito para ese tipo de cadenas, y muchos programadores que aún las usamos, bien sea por costumbre, por cabezonería o por desconocimiento de otras opciones.<br>

<br>
ST> Por lo que he estado viendo para hacer<br>
ST> esto de una forma ajustada (sin desperdiciar memoria) sería “necesario”<br>
ST> utilizar las funciones de memoria dinámica de C (al fin y al cabo estoy<br>
ST> manejando cadenas estilo C ^^).<br>
<br>
No necesariamente. Los operadores new y delete hacen lo mismo que las funciones C para manejar memoria. Tal vez eches de menos la función realloc, pero es una pérdida menor.<br>
<br>
La ventaja de los operadores es que son una abstracción entre el sistema y el programador. Añaden otra capa, ya que es posible sobrecargarlos para implementar otros tipos de control de memoria. Con las funciones C no se puede hacer.<br>

<br>
ST> He escrito el siguiente código y lo he<br>
ST> probado y parece que funciona bien en todos los casos (cadenas largas, con<br>
ST> espacios…):<br>
<br>
A mi entender hay algunos errores y cosas que se pueden mejorar en tu programa. Comento sobre la marcha.<br>
<br>
ST> #include <stdlib.h> //malloc, free, realloc...<br>
ST> static const size_t DEFAULT_CHARS = 2000;<br>
<br>
Un tamaño arbitrario, supongo. Resulta difícil pensar que un usuario "normal" introduzca más de 2000 caracteres cuando le pides una cadena, pero puede pasar. Es incluso más probable si el usuario no es "normal", sino un hacker buscando un buffer para desbordar.<br>

<br>
Cierto que el método getline impide que se lean más de DEFAULT_CHARS caracteres, de modo que estamos protegidos ante ataques de ese tipo, así que de momento, todo bien. :)<br>
<br>
ST> int main(void) {<br>
ST>        const char *concat_str = "este texto se usa para concatenar.";<br>
ST>        char *cad_input = (char*) malloc(sizeof(char) * (DEFAULT_CHARS));<br>
<div class="im">ST>        cout << "Introduce una cadena: ";<br>
</div>ST>        cin.getline(cad_input, DEFAULT_CHARS);<br>
ST>        cad_input = (char*) realloc(cad_input, strlen(cad_input) + 1);<br>
ST>        cad_input[strlen(cad_input)] = '\0';<br>
<br>
Es innecesario añadir el terminador nulo, ya que estaba en la cadena original. Más que nada porque si no fuera así, la función strlen no hubiera funcionado. Precisamente, lo que hace esa función, es contar caracteres hasta que encuentra el primer nulo.<br>

<br>
ST>        cout << "Cadena introducida: " << cad_input << endl;<br>
ST>        char *final_str = (char*)<br>
ST>              calloc(strlen(cad_input) + strlen(concat_str) + 1, sizeof(char<br>
ST> ));<br>
<br>
Me falta un carácter para final_str. Necesitas los suficientes para cad_input, concat_str, para el espacio separador y para el nulo terminador.<br>
<br>
ST>        strcat(final_str, cad_input);<br>
<br>
Nos pasa lo mismo que en el ejemplo anterior. No puedes asegurar que final_str tenga una cadena vacía nada más crearla. De hecho, lo más frecuente es que no sea así. Hay que inicializar siempre todas las variables antes de usarlas, y esto es más importante cuando trabajamos con punteros y con memoria dinámica.<br>

<br>
Al obtener memoria desde el montón (que es desde donde se obtiene la memoria dinámica), no se inicializa el contenido, sólo obtenemos un puntero a la memoria reservada.<br>
<br>
Podrías usar la función strcpy en lugar de strcat, o iniciar la cadena, por ejemplo con final_str[0] = 0;<br>
<br>
ST>        strcat(final_str, " ");<br>
ST>        strcat(final_str, concat_str);<br>
ST>        //strcat(final_str, "\0");<br>
ST>        cout << "Cadena concatenada: " << final_str << endl;<br>
ST>        free(final_str);<br>
ST>        free(cad_input);<br>
ST>        return 0;<br>
ST> }<br>
<br>
ST> La única duda que me surge de esto es si es “bueno” hacer un realloc al<br>
ST> mismo puntero (en este caso cad_input).<br>
<br>
No tiene nada de malo. La pregunta sería si es útil hacerlo. Eso dependerá de cada caso. En este ejemplo, que evidentemente es muy simple, no aporta nada, salvo ahorrar algo de memoria, que de todos modos se libera unos segundos después (o unas milésimas de segundo después). :)<br>

<br>
ST> PD: Por si interesa, encontré en la documentación de GNU el código de las<br>
ST> funciones estándar y demás implementaciones. Se pueden ver en el siguiente<br>
ST> enlace: <a href="http://gcc.gnu.org/onlinedocs/gcc-4.8.1/libstdc++/api/files.html" target="_blank">http://gcc.gnu.org/onlinedocs/gcc-4.8.1/libstdc++/api/files.html</a><br>
<br>
Me guardo el enlace, gracias.<br>
<div class="HOEnZb"><div class="h5"><br>
Hasta pronto.<br>
<br>
--<br>
Salvador Pozo (Administrador)<br>
mailto:<a href="mailto:salvador@conclase.net">salvador@conclase.net</a><br>
Blog con Clase: <a href="http://blogconclase.wordpress.com" target="_blank">http://blogconclase.wordpress.com</a><br>
Con Clase: <a href="http://conclase.net" target="_blank">http://conclase.net</a><br>
_______________________________________________<br>
Lista de correo Cconclase <a href="mailto:Cconclase@listas.conclase.net">Cconclase@listas.conclase.net</a><br>
<a href="http://listas.conclase.net/mailman/listinfo/cconclase_listas.conclase.net" target="_blank">http://listas.conclase.net/mailman/listinfo/cconclase_listas.conclase.net</a><br>
Bajas: <a href="http://listas.conclase.net/index.php?gid=2&mnu=FAQ" target="_blank">http://listas.conclase.net/index.php?gid=2&mnu=FAQ</a></div></div></blockquote></div><br></div>