<div dir="ltr"><p class="" style="margin-bottom:0.0001pt"><span style="font-size:12pt;font-family:Arial,sans-serif">Muchas gracias Salvador. No sabía que existía un blog
de C con Clase! Un artículo interesante, me guardo el blog a la lista de los
que frecuento =)</span></p>

<p class="" style="margin-bottom:0.0001pt"><span style="font-size:12pt;font-family:Arial,sans-serif">Soy consciente de la existencia de la clase string (y te aseguro que es la
que voy a utilizar siempre ;-P), mi intención con esto era simplemente
comprender el manejo de cadenas estilo C (según he leído hay mucho código
heredado y conviene saber del tema). Por lo que he estado viendo para hacer
esto de una forma ajustada (sin desperdiciar memoria) sería “necesario”
utilizar las funciones de memoria dinámica de C (al fin y al cabo estoy
manejando cadenas estilo C ^^). He escrito el siguiente código y lo he probado
y parece que funciona bien en todos los casos (cadenas largas, con espacios…):</span></p>

<p class="" style="margin-bottom:0.0001pt"><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas;color:blue">#include</span><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas">
<span style="color:rgb(163,21,21)"><stdlib.h></span> <span style="color:green">//malloc,
free, realloc...</span></span></p>

<p class="" style="margin-bottom:0.0001pt"><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas;color:blue">static</span><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas">
<span style="color:blue">const</span> size_t DEFAULT_CHARS = 2000;</span></p>

<p class="" style="margin-bottom:0.0001pt"><br></p>

<p class="" style="margin-bottom:0.0001pt"><span style="font-size:9.5pt;font-family:Consolas;color:blue">int</span><span style="font-size:9.5pt;font-family:Consolas"> main(<span style="color:blue">void</span>) {</span></p>


<p class="" style="margin-bottom:0.0001pt"><span style="font-size:9.5pt;font-family:Consolas">       <span style="color:blue">const</span> <span style="color:blue">char</span>
*concat_str = <span style="color:rgb(163,21,21)">"este texto se usa para
concatenar."</span>;</span></p>

<p class="" style="margin-bottom:0.0001pt"><span style="font-size:9.5pt;font-family:Consolas">       </span><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas;color:blue">char</span><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas"> *cad_input = (<span style="color:blue">char</span>*)
malloc(<span style="color:blue">sizeof</span>(<span style="color:blue">char</span>)
* (DEFAULT_CHARS));</span></p>

<p class="" style="margin-bottom:0.0001pt"><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas"> </span></p>

<p class="" style="margin-bottom:0.0001pt"><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas">       cout << <span style="color:rgb(163,21,21)">"Introduce
una cadena: "</span>;</span></p>

<p class="" style="margin-bottom:0.0001pt"><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas">       cin.getline(cad_input, DEFAULT_CHARS);</span></p>

<p class="" style="margin-bottom:0.0001pt"><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas"> </span></p>

<p class="" style="margin-bottom:0.0001pt"><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas">       cad_input = (<span style="color:blue">char</span>*)
realloc(cad_input, strlen(cad_input) + 1);</span></p>

<p class="" style="margin-bottom:0.0001pt"><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas">       cad_input[strlen(cad_input)] = <span style="color:rgb(163,21,21)">'\0'</span>;</span></p>

<p class="" style="margin-bottom:0.0001pt"><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas">       </span><span style="font-size:9.5pt;font-family:Consolas">cout << <span style="color:rgb(163,21,21)">"Cadena
introducida: "</span> << cad_input << endl;</span></p>

<p class="" style="margin-bottom:0.0001pt"><span style="font-size:9.5pt;font-family:Consolas"> </span></p>

<p class="" style="margin-bottom:0.0001pt"><span style="font-size:9.5pt;font-family:Consolas">       </span><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas;color:blue">char</span><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas"> *final_str = (<span style="color:blue">char</span>*) </span></p>


<p class="" style="margin-bottom:0.0001pt"><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas">             calloc(strlen(cad_input) + strlen(concat_str)
+ 1, <span style="color:blue">sizeof</span>(<span style="color:blue">char</span>));</span></p>

<p class="" style="margin-bottom:0.0001pt"><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas"> </span></p>

<p class="" style="margin-bottom:0.0001pt"><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas">       strcat(final_str, cad_input);</span></p>

<p class="" style="margin-bottom:0.0001pt"><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas">       strcat(final_str, <span style="color:rgb(163,21,21)">" "</span>);</span></p>

<p class="" style="margin-bottom:0.0001pt"><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas">       strcat(final_str, concat_str);</span></p>

<p class="" style="margin-bottom:0.0001pt"><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas">       <span style="color:green">//strcat(final_str,
"\0");</span></span></p>

<p class="" style="margin-bottom:0.0001pt"><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas"> </span></p>

<p class="" style="margin-bottom:0.0001pt"><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas">       cout << <span style="color:rgb(163,21,21)">"Cadena
concatenada: "</span> << final_str << endl;</span></p>

<p class="" style="margin-bottom:0.0001pt"><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas"> </span></p>

<p class="" style="margin-bottom:0.0001pt"><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas">       free(final_str);</span></p>

<p class="" style="margin-bottom:0.0001pt"><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas">       </span><span style="font-size:9.5pt;font-family:Consolas">free(cad_input);</span></p><p class="" style="margin-bottom:0.0001pt">
<span style="font-size:9.5pt;font-family:Consolas"><br></span></p>

<p class="" style="margin-bottom:0.0001pt"><span style="font-size:9.5pt;font-family:Consolas">       <span style="color:blue">return</span> 0;</span></p>

<p class="" style="margin-bottom:0.0001pt"><span style="font-size:9.5pt;font-family:Consolas">}</span></p>

<p class="">La única duda que me surge de esto es si es “bueno” hacer un
realloc al mismo puntero (en este caso cad_input). Tampoco hago comprobaciones
de ningún tipo y soy consciente de que se deben hacer (comprobar que cad_input
no es NULL etc…), como he comentado es simplemente un ejercicio para satisfacer
mi curiosidad y manejarme un poco con las cadenas estilo C ^^</p>

<p class="">Muchas gracias por todo Salvador, has sido de gran ayuda =)</p>

<p class="">PD: Por si interesa, encontré en la documentación de GNU el
código de las funciones estándar y demás implementaciones. Se pueden ver en el
siguiente enlace: <a href="http://gcc.gnu.org/onlinedocs/gcc-4.8.1/libstdc++/api/files.html">http://gcc.gnu.org/onlinedocs/gcc-4.8.1/libstdc++/api/files.html</a></p></div><div class="gmail_extra"><br><br><div class="gmail_quote">
El 7 de agosto de 2013 19:23, 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">
Hola:<br>
<br>
El pasado 2013-08-07 14:59:38, Sergio Torró escribió:<br>
<br>
ST> Muchas gracias por tu respuesta Salvador, te has explicado perfectamente :-)<br>
ST> Deduzco que si quisiera concatenar cadenas que el usuario introduce por<br>
ST> teclado, tendría que asignar memoria dinámicamente para poder hacerlo,<br>
ST> ¿verdad?<br>
<br>
Efectivamente, necesitarás memoria dinámica, pero eso plantea algunos problemas que pasaré a comentarte sobre tu programa.<br>
<br>
ST> He escrito el siguiente código y me funciona bien, pero si hay<br>
ST> algún detalle de los que no se ven a simple vista me encantaría saberlo ;-P<br>
ST> int main(void)<br>
ST> {<br>
ST>        char *cad_input = new char;<br>
<br>
Esto no es correcto. La expresión "new char" sólo reserva memoria para un carácter, y difícilmente podrás almacenar una cadena en un espacio tan pequeño.<br>
<br>
Para reservar memoria para más de un carácter hay que usar el operador new[], de este modo:<br>
<br>
char *cad_input = new char[32];<br>
<br>
El problema de esto es que tenemos que dimensionar la cadena antes de saber qué tamaño va a tener, puesto que aún no hemos leído nada desde el teclado, ni tampoco podemos prever qué tipo de cadena va a introducir el usuario.<br>

<br>
ST>        char cad_concat[] = "-> concatenado con este texto.";<br>
ST>        char *cad_final = new char;<br>
<br>
Lo mismo se aplica a cad_final.<br>
<br>
ST>        cout << "Introduce una cadena: ";<br>
ST>        cin >> cad_input;<br>
ST>        strcat(cad_final, cad_input);<br>
<br>
Aquí hay otro problema. No has inicializado la cadena cad_final, y concatenas el contenido inicial, que no conocemos, con el introducido por el usuario. El resultado es imprevisible.<br>
<br>
ST>        strcat(cad_final, " ");<br>
ST>        strcat(cad_final, cad_concat);<br>
ST>        cout << endl << cad_final << endl;<br>
ST>        delete cad_input;<br>
ST>        delete cad_final;<br>
<br>
Como dices en tu siguiente mensaje, si se usa new[] hay que usar delete[], pero en este caso no has usado los corchetes, por lo que, aún estando mal el programa, al menos los operadores new y delete son coherentes. :)<br>

<br>
ST>        return 0;<br>
ST> }<br>
<br>
ST> Y en este último caso imagino que es mejor utilizar la asignación dinámica<br>
ST> de memoria de C++ y evitar malloc() y realloc(), ¿verdad?<br>
<br>
Programando en C++ siempre es preferible usar los operadores que las funciones para asignación de memoria. Más que nada porque los operadores se pueden sobrecargar o redefinir, para, por ejemplo, diseñar tu propia gestión de memoria.<br>

<br>
Por cierto, que para evitar los inconvenientes con las cadenas es preferible usar la clase para cadenas definida en la cabecera <string>.<br>
<br>
Tu programa, usando esa clase, queda así:<br>
----8<------<br>
#include <iostream><br>
#include <string><br>
<br>
using namespace std;<br>
<br>
int main(void)<br>
{<br>
       string cad_input;<br>
       string cad_concat("-> concatenado con este texto.");<br>
       string cad_final;<br>
<br>
       cout << "Introduce una cadena: ";<br>
       getline(cin, cad_input);<br>
<br>
       cad_final = cad_input + " " + cad_concat;<br>
<br>
       cout << endl << cad_final << endl;<br>
<br>
       return 0;<br>
}<br>
----8<------<br>
<br>
Utilizo la función "getline" en lugar del operador >> para leer cadenas porque de ese modo se pueden leer espacios. El operador >> deja de leer al encontrar el primer espacio, y deja el resto de la cadena en el buffer de entrada, con lo que siguientes lecturas pueden dar un resultado inesperado.<br>

<br>
En lugar de la función strcat, puedes usar el operador + para concatenar cadenas, o también el operador +=, si lo prefieres.<br>
<br>
Recomiendo visitar el artículo del blog sobre validación de dato, ya que estamos hablando del tema. :)<br>
<br>
<a href="http://blogconclase.wordpress.com/2013/06/07/validar-datos-en-c/" target="_blank">http://blogconclase.wordpress.com/2013/06/07/validar-datos-en-c/</a><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><br>
</div></div></blockquote></div><br></div>