<div dir="ltr"><br><div><p class="" style="margin-bottom:0.0001pt"><span style="font-size:12pt;font-family:Arial,sans-serif">Muchas gracias por tu respuesta Salvador, te has
explicado perfectamente :-)</span></p>

<p class="" style="margin-bottom:0.0001pt"><span style="font-size:12pt;font-family:Arial,sans-serif">Deduzco que si quisiera concatenar cadenas que el usuario introduce por
teclado, tendría que asignar memoria dinámicamente para poder hacerlo, ¿verdad?
He escrito el siguiente código y me funciona bien, pero si hay algún detalle de
los que no se ven a simple vista me encantaría saberlo ;-P</span></p>

<p class="" style="margin-bottom:0.0001pt"><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas;color:blue">int</span><span lang="EN-US" 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 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">       <span style="color:blue">char</span>
*cad_input = <span style="color:blue">new</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><span style="font-size:9.5pt;font-family:Consolas;color:blue">char</span><span style="font-size:9.5pt;font-family:Consolas"> cad_concat[] = <span style="color:rgb(163,21,21)">"->
concatenado con este texto."</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_final = <span style="color:blue">new</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">       </span><span 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 style="font-size:9.5pt;font-family:Consolas">       cin
>> cad_input;</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">strcat(cad_final,
cad_input);</span></p>

<p class="" style="margin-bottom:0.0001pt"><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas">       strcat(cad_final, <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(cad_final, cad_concat);</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 << endl << cad_final
<< 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">       <span style="color:blue">delete</span>
cad_input;</span></p>

<p class="" style="margin-bottom:0.0001pt"><span lang="EN-US" style="font-size:9.5pt;font-family:Consolas">       <span style="color:blue">delete</span>
cad_final;</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">       <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="">Y en este último caso imagino que es mejor utilizar la
asignación dinámica de memoria de C++ y evitar malloc() y realloc(), ¿verdad?</p>

<p class="">Un saludo y gracias por tu tiempo.</p></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">El 6 de agosto de 2013 20:47, 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-06 16:48:20, Sergio Torró escribió:<br>
<br>
ST> Muy buenas a todos. Me gustaría comentar una duda (seguramente muy tonta)<br>
ST> sobre el manejo de cadenas estilo C. Tengo el siguiente código que funciona<br>
ST> perfectamente:<br>
ST> #include <iostream><br>
ST> using std::cout;<br>
ST> using std::endl;<br>
ST> #include <cstring><br>
ST> using std::strcat;<br>
ST> int main(void) {<br>
ST>        char cadena1[] = "Hola";<br>
ST>        char cadena2[] = "Perico";<br>
ST>        strcat(cadena1, " ");<br>
ST>        strcat(cadena1, cadena2);<br>
ST>        cout << cadena1 << endl;<br>
ST>        return 0;<br>
ST> }<br>
ST> Echándole un ojo a la declaración de strcat veo que sus parámetros son<br>
ST> punteros (char*, const char*) y se me ocurrió probar a declarar mis dos<br>
ST> cadenas de caracteres como tales: char *cadena1 = "Hola"; Si hago ese<br>
ST> cambio, no funciona.<br>
ST> Creo entender la diferencia entre un array de chars y un puntero: si no me<br>
ST> equivoco el array reserva espacio para cada char que contiene la cadena. Si<br>
ST> lo declaro como un puntero, se reserva espacio para almacenar simplemente<br>
ST> un puntero que puede apuntar a cualquier cadena de chars. Mi duda es: si<br>
ST> esa función está esperando un puntero a una cadena, ¿no debería funcionar<br>
ST> si le paso eso mismo? ¿No se supone que el nombre del array (en este caso<br>
ST> cadena1) es un puntero al primer elemento de la cadena?<br>
<br>
A ver si puedo explicar con claridad lo que está pasando en este ejemplo.<br>
<br>
Cuando declaras las cadenas como arrays, el compilador, como bien dices, reserva espacio suficiente para contener la cadena declarada.<br>
<br>
El problema no es tanto cuanta memoria reserva el compilador como dónde la reserva.<br>
<br>
Cuando se trata de un array, la memoria para las cadenas se obtiene de la pila, y los literales de inicialización, en este caso "Hola" y "Perico" se copian desde su origen inicial a las direcciones asignadas a los arrays.<br>

<br>
En este caso, el programa funciona porque se dan algunas circunstancias "afortunadas".<br>
<br>
Una de ellas es que las cadenas son cortas, pero al copiar una cadena a continuación de la otra, estamos corrompiendo la memoria que no pertenece al array, y por lo tanto, corrompemos la pila. Como son cadenas cortas, tenemos al suerte de no corromper dados sensibles, pero si fueran cadenas más largas esto no sería así.<br>

<br>
La otra es el orden en que hemos declarado las variables.<br>
<br>
Prueba esto:<br>
----8<------<br>
<div class="im">#include <iostream><br>
using std::cout;<br>
using std::endl;<br>
<br>
#include <cstring><br>
using std::strcat;<br>
<br>
int main(void) {<br>
       char cadena1[] = "Hola";<br>
       char cadena2[] = "Perico";<br>
</div>       cadena2[6] = ' ';<br>
       cout << cadena2 << endl;<br>
       return 0;<br>
}<br>
----8<------<br>
<br>
La salida, en este caso, es "Perico Hola". Esto es porque al almacenarse en la pila, las variables se crean de arriba a abajo, es decir, cada variable local tiene direcciones de memoria menores que las anteriores. El resultado es que primero se almacena en la pila "Hola", y a continuación, en posiciones correlativas, pero menores, "Perico", con el carácter nulo terminador.<br>

<br>
En este programa hemos sustituido el terminador de "Perico" por un espacio, y por eso se concatenan (aparentemente) las dos cadenas.<br>
<br>
Si declaras las variables en otro orden, probablemente destruyas una al intentar concatenarlas.<br>
<br>
Cuando sustituyes las cadenas por punteros, los punteros se siguen almacenando en la pila, pero en lugar de copiar las cadenas al inicial el programa, sólo copia las direcciones. Las cadenas se almacenan junto con el programa ejecutable.<br>

<br>
La mayor diferencia en este caso es que el sistema operativo protege las direcciones de memoria donde se almacena el programa para que no puedan ser modificadas, o al menos para detectar cuando han sido modificadas. Esto es lo que provoca la excepción "segmentation fault".<br>

<br>
Una pista en este caso son los mensajes de aviso del compilador:<br>
<br>
\main.cpp|9|warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]|<br>
<br>
Ya te está avisando que estás intentando convertir una cadena constante en un puntero a char, y que eso está desaconsejado.<br>
<br>
Constante significa que no puede modificarse su valor, y eso es precisamente lo que intentas hacer con strcat.<br>
<br>
En cualquiera de los dos casos estamos diseñando mal el programa, ya que intentamos copiar cadenas usando objetos (punteros o arrays), que no tienen la capacidad suficiente para contenerlas.<br>
<br>
ST> He pensado que<br>
ST> tiene que ver con la implementación de la función strcat la cual me<br>
ST> gustaría ver, ¿hay alguna forma donde pueda ver la implementación de dichas<br>
ST> funciones? Vengo de Java y estoy muy acostumbrado en Eclipse a hacer un<br>
ST> “Control + clic” en el elemento que quiero ver su implementación ^^<br>
ST> Imagino que para el compilador de GNU no será un problema ver la<br>
ST> implementación (¿simplemente descargar las fuentes verdad?). ¿Es posible<br>
ST> hacerlo también en Visual Studio? Uso Code::Blocks y Visual Studio a partes<br>
ST> iguales.<br>
<br>
<br>
No he encontrado los fuentes para strcat, tampoco he buscado mucho, la verdad. :) Sobre todo porque la implementación de esa función no tiene importancia en este caso.<br>
<br>
Una posible implementación podría ser:<br>
<br>
----8<------<br>
char *strcat(char *dst, const char *src)<br>
{<br>
    char *ret = dst;<br>
<br>
    for (; *dst; ++dst);<br>
    while ((*dst++ = *src++) != '\0');<br>
    return ret;<br>
}<br>
----8<------<br>
<br>
Sin embargo, estas funciones ni siquiera tienen por qué estar escritas en C, ya que generalmente se trata de librerías de uso frecuente, suelen estar muy optimizadas, y frecuentemente se escriben en ensamblador.<br>
<br>
Hasta pronto.<br>
<span class="HOEnZb"><font color="#888888"><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></font></span></blockquote></div><br></div>