Autor
|
Tema: dudas con strcpy (Leído 5,582 veces)
|
m@o_614
Desconectado
Mensajes: 389
|
Saludos
tengo una duda con respecto al uso de strcpy
si tengo una cadena por ejemplo:
char *cadena = "hola mundo";
y despues quiero cambiar el contenido de esa cadena, puedo usar el strcpy para eso??
strcpy(cadena,"lo que quieras escribir");
gracias
|
|
|
En línea
|
|
|
|
Yoel Alejandro
|
Ok, hay varios aspectos implícitos en tu pregunta. La función
strcpy( char *s1, const char *s2)
copia el contenido de s2 en s1, añadiendo al final de s1 un carácter nulo de terminación '\0'. La única consideración es que s1 contenga el suficiente espacio disponible para copiar todos los caracteres (al menos la longitud de s2 más uno).
Esto por supuesto requiere que se pueda escribir en el espacio asignado a s1. Si declaras
char *cadena = "hola mundo";
entonces cadena se considerará un string constante y ya no podrás escribir nada nuevo en él. Pero la declaración:
char cadena[] = "hola mundo";
sí permite rescribir el contenido de cadena (siempre y cuando la nueva cadena sea de longitud menor o igual a la que tenías primero, de lo contrario no habrá espacio disponible suficiente). Por ejemplo, puedes poner:
strcpy( cadena, "Pepe"); puts( cadena );
y verás como ahora escribe "Pepe".
---------------------------------------------------------------------------------- NOTA. En cuánto a la declaración de string constantes no se con exactitud si la forma de interpretar la sentencia depende del compilador o de la versión de C, o de si es en C ó en C++. Que alguno de los usuarios más versados en el tema por favor nos complemente.
|
|
|
En línea
|
Saludos, Yoel. P.D..- Para mayores dudas, puedes enviarme un mensaje personal (M.P.)
|
|
|
milx86
Desconectado
Mensajes: 42
|
Concuerdo con yoel, tienes que tener en cuenta 2 puntos importantes: 1. Cito: "Es nuestra responsabilidad que en la cadena de destino haya suficiente espacio reservado para copiar lo que queremos. Si no es así, estaremos sobreescribiendo direcciones de memoria en las que no sabemos qué hay." Fuente http://www.nachocabanes.com/c/curso/cc05.php
Asi que mejor te recomiendo usar strncpy. 2. Estas declarando una constante de caracteres que no puedes modificar. Para no hacer copia y pega, te invito a leer esto, no es mucho y estoy seguro aclarará un poco más tus dudas. Fuente: http://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C/Punteros#Punteros_a_cadenas_de_caracteresSuerte.
|
|
|
En línea
|
La abstracción es la clave para lidiar con la complejidad.
|
|
|
leosansan
Desconectado
Mensajes: 1.314
|
Concuerdo con yoel, tienes que tener en cuenta 2 puntos importantes: ......................................
Totalmente de acuerdo con ambos. Cito una indicación de la página de cplusplus : strcpy
char * strcpy ( char * destination, const char * source );
Copy string Copies the C string pointed by source into the array pointed by destination, including the terminating null character (and stopping at that point).
To avoid overflows, the size of the array pointed by destination shall be long enough to contain the same C string as source (including the terminating null character), and should not overlap in memory with source.
Sin embargo ..... supongo que es el propio compilador el que lleva a cabo la operación de ampliar el espacio de la cadena receptora, que en principio es de 10 y podría provocar el overflow, pero en la práctica eso no sucede.
Está es la salida al código de ejemplo: Cadena str1 antes del cambio: A ver si cabe la cadena str1 en srt2
Cadena str2 antes del cambio: leosansan
Lo que queda en str1: abe la cadena str1 en srt2
Copiado, nuevo str2: A ver si cabe la cadena str1 en srt2
Y la cadena str2 impresa caracter a caracter: A ver si cabe la cadena str1 en srt2
longitud de la nueva cadena str2= 36 Process returned 0 (0x0) execution time : 1.500 s Press any key to continue.
Como pueden observar, str2 "se metió" en la cadena str1 que originalmente erra de dimensión 10 sin problemas.
Eso si, destacar que si str2 no tiene suficiente dimensión quedará en la cadena original el "resto" de la dicha cadena:#include <stdio.h> #include <string.h> int main () { int i; char str1[ ]="A ver si cabe la cadena str1 en srt2"; char str2[10]="leosansan"; printf ("\nCadena str1 antes del cambio:\n%s",str1); printf ("\n\nCadena str2 antes del cambio:\n%s",str2); strcpy (str2,str1); printf ("\n\nLo que queda en str1: %s\n\nCopiado, nuevo str2:\n%s\n\n",str1,str2); printf("\n\nY la cadena str2 impresa caracter a caracter:\n "); for( i=0;str2[i]; i++) printf( "%c",str2[i] ); printf( "\n\nlongitud de la nueva cadena str2=\n%d", strlen(str2) ); return 0; }
Espero no haberme liado con este rollito, ¿o tal vez si?. Ya me contaran ustedes.¡¡¡¡ Saluditos! ..... !!!!
|
|
|
En línea
|
|
|
|
amchacon
Desconectado
Mensajes: 1.211
|
NOTA. En cuánto a la declaración de string constantes no se con exactitud si la forma de interpretar la sentencia depende del compilador o de la versión de C, o de si es en C ó en C++. Que alguno de los usuarios más versados en el tema por favor nos complemente.
Te refieres a: char *cadena = "hola mundo";
En ningún compilador de C/C++ podrás modificar el contenido de cadena. Más que nada porque lo que estás haciendo es declarar un puntero que apunta a una cadena literal (y los valores literales son constantes por definición). Excepción los arrays de chars, donde por comodidad sintáctica se te permite escribir esta sentencia: char cadena[] = {'h','o','l','a',' ','m','u','n','d','o','\0'};
De esta forma: char cadena[] = "hola mundo";
Totalmente de acuerdo con ambos. Cito una indicación de la página de cplusplus : Sin embargo ..... supongo que es el propio compilador el que lleva a cabo la operación de ampliar el espacio de la cadena receptora, que en principio es de 10 y podría provocar el overflow, pero en la práctica eso no sucede.
Está es la salida al código de ejemplo:Como pueden observar, str2 "se metió" en la cadena str1 que originalmente erra de dimensión 10 sin problemas.
Eso si, destacar que si str2 no tiene suficiente dimensión quedará en la cadena original el "resto" de la dicha cadena:#include <stdio.h> #include <string.h> int main () { int i; char str1[ ]="A ver si cabe la cadena str1 en srt2"; char str2[10]="leosansan"; printf ("\nCadena str1 antes del cambio:\n%s",str1); printf ("\n\nCadena str2 antes del cambio:\n%s",str2); strcpy (str2,str1); printf ("\n\nLo que queda en str1: %s\n\nCopiado, nuevo str2:\n%s\n\n",str1,str2); printf("\n\nY la cadena str2 impresa caracter a caracter:\n "); for( i=0;str2[i]; i++) printf( "%c",str2[i] ); printf( "\n\nlongitud de la nueva cadena str2=\n%d", strlen(str2) ); return 0; }
Espero no haberme liado con este rollito, ¿o tal vez si?. Ya me contaran ustedes. Pues si te has liado, prueba este otro código: #include <stdio.h> #include <string.h> int main () { int i; char str1[ ]="Cosita grande y hermosa"; char str2[10]="leosansan"; printf ("\nCadena str1 antes del cambio:\n%s",str1); printf ("\n\nCadena str2 antes del cambio:\n%s",str2); strcpy (str2,str1); printf ("\n\nLo que queda en str1: %s\n\nCopiado, nuevo str2:\n%s\n\n",str1,str2); printf("\n\nY la cadena str2 impresa caracter a caracter:\n "); for( i=0; str2[i]; i++) printf( "%c",str2[i] ); printf( "\n\nlongitud de la nueva cadena str2=\n%d\n", strlen(str2) ); return 0; }
Fijate en el contenido de str1: nde y hermosa Ha dado overflow, te has salido del espacio de str2 y estás sobreescribiendo la cadena str1. ¿Por que en el otro ejemplo si funcionaba? Pues porque lo has interpretado mal: A ver si cabe la cadena str1 en srt2 abe la cadena str1 en srt2 Se ha comido lo que está en negrita, lo que pasa esque no suena raro y lo has pasado por alto sin darte cuenta.
|
|
« Última modificación: 15 Marzo 2014, 21:34 pm por amchacon »
|
En línea
|
|
|
|
Yoel Alejandro
|
En el caso que plantea leosansan, supongo que dependerá del compilador. Probablemente cualquier compilador moderno tomará previsiones adecuadas si la cadena de origen excede en longitud a la cadena de destino.
Sin embargo la filosofía de C es que "los programadores saben lo que están haciendo", por eso pienso que a pesar de la ayuda que pueda proporcionar el compilador, un buen programador de C debe garantizarse por sí mismo la consistencia de este tipo de operaciones. Así que al autor del post: pues, ya lo sabes!!!
Interesante un detalle adicional de la cita de cplusplus y que se me había pasado por alto: Las cadenas origen y destino no deben solaparse. Esta es otra consideración a tener en cuenta, no se debe intentar escribir una cadena sobre sí misma.
NOTA: Estas dificultades se evitan cómodamente usando la clase string de C++. Pero personalmente creo que quién se quiera formar como un verdadero programador debería pasar primero por C (con todas sus dificultades asociadas), y luego ir a C++. Hay que "ensuciarse" primero para aprender bien. Bueno, al menos es mi criterio, no se qué opinen los demás (?)
|
|
|
En línea
|
Saludos, Yoel. P.D..- Para mayores dudas, puedes enviarme un mensaje personal (M.P.)
|
|
|
amchacon
Desconectado
Mensajes: 1.211
|
En el caso que plantea leosansan, supongo que dependerá del compilador. Probablemente cualquier compilador moderno tomará previsiones adecuadas si la cadena de origen excede en longitud a la cadena de destino. Eso no es así, ya se lo desmentí a Leosan. Hacer esas aproximaciones suele dar muy malos resultados. Luego ocurren los errores extraños y inexplicables, los crasheos aleatorios... Como regla general, siempre hay que ceñirse a lo que te diga el creador de la función. Cualquier truco o atajo que intentes no está garantizado contra errores y probablemente acabe muy mal. Estas dificultades se evitan cómodamente usando la clase string de C++. Pero personalmente creo que quién se quiera formar como un verdadero programador debería pasar primero por C (con todas sus dificultades asociadas), y luego ir a C++. Hay que "ensuciarse" primero para aprender bien. Bueno, al menos es mi criterio, no se qué opinen los demás (?)
Un buen programador es el que es capaz de escribir la solución de un problema paso a paso. El usar un lenguaje u otro solo sirve para probar tu solución en una computadora. Lo que si es verdad esque es importante conocer los mecanismos de abstracción (grafos, listas, vectores...). Y una forma práctica de aprenderlo es re-hacer la librería básica del lenguaje. PD: Un buen programador no tiene problemas en adaptarse de un lenguaje a otro en poco tiempo. Aunque no lo haya visto nunca, normalmente son todos muy parecidos.
|
|
|
En línea
|
|
|
|
leosansan
Desconectado
Mensajes: 1.314
|
................................................
Fijate en el contenido de str1: Ha dado overflow, te has salido del espacio de str2 y estás sobreescribiendo la cadena str1.
¿Por que en el otro ejemplo si funcionaba? Pues porque lo has interpretado mal: Se ha comido lo que está en negrita, lo que pasa es que no suena raro y lo has pasado por alto sin darte cuenta.
La salida tuya: Cadena str1 antes del cambio: Cosita grande y hermosa
Cadena str2 antes del cambio: leosansan
Lo que queda en str1: nde y hermosa
Copiado, nuevo str2: Cosita grande y hermosa
Y la cadena str2 impresa caracter a caracter: Cosita grande y hermosa
longitud de la nueva cadena str2= 23
Process returned 0 (0x0) execution time : 0.102
Por ejemplo esta otra salida: Cadena str1 antes del cambio: Cosita grande y hermosa
Cadena str2 antes del cambio: leosansan
Lo que queda en str1: nde y hermosa
Copiado, nuevo str2: Cosita grande y hermosa
Y la cadena str2 impresa caracter a caracter: Cosita grande y hermosa
Cadena str0 despues del cambio:
Gran Canaria es Cosita grande y hermosa
Cadena str3 despues del cambio:
leosansan es de Gran Canaria
Process returned 0 (0x0) execution time : 1.165 s Press any key to continue.
A este código:#include <stdio.h> #include <string.h> int main () { int i; char str0[ ]="Gran Canaria es Cosita grande y hermosa"; char str1[ ]="Cosita grande y hermosa"; char str2[ ]="leosansan"; char str3[ ]="leosansan es de Gran Canaria"; printf ("\nCadena str1 antes del cambio:\n%s",str1); printf ("\n\nCadena str2 antes del cambio:\n%s",str2); strcpy (str2,str1); printf ("\n\nLo que queda en str1: %s\n\nCopiado, nuevo str2:\n%s\n\n",str1,str2); printf("\n\nY la cadena str2 impresa caracter a caracter:\n "); for( i=0; str2[i]; i++) printf( "%c",str2[i] ); printf( "\n\nCadena str0 despues del cambio:\n\n%s",str0); printf ("\n\nCadena str3 despues del cambio:\n\n%s\n\n",str3); return 0; }
Lo realmente raro es que si declaro varias cadenas str, tres o cuatro, además de str1 y str2, lo que queda en str1 siempre es el resto de lo que teóricamente "sobra en str2, en tu ejemplo y en el mio. Será casualidad o no, pero es un resultado cuando menos inesperado. ¿Por qué juntamente queda en str1 y no en las otras cadenas que he declarado?. He ahí mi gran duda, ¿será casualidad o es un comportamiento normal de la función strcpy "dejar" el resto de la cadena que no quepa en str2?. Y a los ejemplos me remito, claro que tan sólo son dos ejemplos y ya sabemos que no se puede pasr del particular al general, pero ......
Pero lo que dice el manual está claro, yo sólo pongo de manifiesto un hecho contrastado en esos dos ejemplos. ¡¡¡¡ Saluditos! ..... !!!!
|
|
|
En línea
|
|
|
|
Yoel Alejandro
|
Amchacon, por eso dije ... "supongo", porque la verdad yo no se.
No lo se porque en lo particular siempre trato de programar de forma "segura", atendiendo a las especificaciones de la biblioteca estándar de C, y la verdad pocas veces me he puesto a ver qué pasa si hago tal o cuál cosa de manera insegura. Prefiero irme de una vez por lo sano, y así evitar crasheos, etc.
Pero respecto a lo de varios lenguajes lo que quise decir es que específicamente en el aprendizaje de C/C++, me parece más adecuado aprender primero a programar correctamente en C, y luego pasarse a C++ el cual básicamente amplica las capacidades del primero. Eso en lugar de mezclar el C y el C++, lo que constituye una mala costumbre según el criterio unánime creo que todos los que opinamos aquí.
Otra mala costumbre, y lamentablemente extendida entre algunos maestros, es no guiarse por el C estándar. Referirse a gotoxy(), getch(), etc., de la manera más natural (y descarada), sin especificar ni aclarar que son no funciones estándares. No digo que no usen esas funciones, pero deben dejar en claro que son privativas y generalmente usadas en Windows.
|
|
« Última modificación: 15 Marzo 2014, 23:29 pm por yoel_alejandro »
|
En línea
|
Saludos, Yoel. P.D..- Para mayores dudas, puedes enviarme un mensaje personal (M.P.)
|
|
|
amchacon
Desconectado
Mensajes: 1.211
|
He ahí mi gran duda, ¿será casualidad o es un comportamiento normal de la función strcpy "dejar" el resto de la cadena que no quepa en str2?. Y a los ejemplos me remito, claro que tan sólo son dos ejemplos y ya sabemos que no se puede pasr del particular al general, pero .... Tengo una teoría. Suponte este caso: char inicia[] = "Entrada larga"; char destino[5] = "abcd";
La memoria podría ser: 00 a --> Destino 01 b 02 c 03 d 04 '\0' 05 E --> Original 06 n 07 t 08 r 09 a 10 ' ' 11 l 12 a 13 r 14 g 15 a 16 '\0' Y hacemos el strcpy: 00 E --> Destino 01 n 02 t 03 r 04 a 05 d --> Original 06 a 07 ' ' 08 l 09 a 10 r 11 g 12 a 13 '\0' 14 g 15 a 16 '\0' Fijate que el puntero "original" apunta a las ultimas posiciones de "destino". No esque deje lo que sobre, esque estamos viendo los ultimos caracteres de la cadena destino! Lo acabo de probar y efectivamente str1 da la salida que esperaba: "da larga" #include <stdio.h> #include <string.h> int main () { char str1[] = "Entrada larga"; char str2[5] = "abcd"; strcpy (str2,str1); printf ("\n\nLo que queda en str1: %s\n\nCopiado, nuevo str2:\n%s\n\n",str1,str2); printf("\n\nY la cadena str2 impresa caracter a caracter:\n "); int i; for( i=0; str2[i]; i++) printf( "%c",str2[i] ); return 0; }
Podríamos "rematar" la teoría modificando un valor de str2. A ver si esos cambios aparecen en str1: #include <stdio.h> #include <string.h> int main () { char str1[] = "Entrada larga"; char str2[5] = "abcd"; strcpy (str2,str1); str2[10] = 'Z'; printf ("\n\nLo que queda en str1: %s\n\nCopiado, nuevo str2:\n%s\n\n",str1,str2); printf("\n\nY la cadena str2 impresa caracter a caracter:\n "); int i; for( i=0; str2[i]; i++) printf( "%c",str2[i] ); return 0; }
Cuya salida es: ¡La Z aparece en las dos cadenas! Parece que mi teoria tiene sentido : ) No lo se porque en lo particular siempre trato de programar de forma "segura", atendiendo a las especificaciones de la biblioteca estándar de C, y la verdad pocas veces me he puesto a ver qué pasa si hago tal o cuál cosa de manera insegura. Prefiero irme de una vez por lo sano, y así evitar crasheos, etc. Eso está bien ^^ Pero respecto a lo de varios lenguajes lo que quise decir es que específicamente en el aprendizaje de C/C++, me parece más adecuado aprender primero a programar correctamente en C, y luego pasarse a C++ el cual básicamente amplica las capacidades del primero. Eso en lugar de mezclar el C y el C++, lo que constituye una mala costumbre según el criterio unánime creo que todos los que opinamos aquí. Bueno yo hize eso, aunque mucha gente empezó a programar en Python o en Java. Luego no tuvieron problema en pasar de un lenguaje a otro. Como siempre, lo importante no es el lenguaje sino en saber describir la solución a un problema. Otra mala costumbre, y lamentablemente extendida entre algunos maestros, es no guiarse por el C estándar. Referirse a gotoxy(), getch(), etc., de la manera más natural (y descarada), sin especificar ni aclarar que son no funciones estándares. No digo que no usen esas funciones, pero deben dejar en claro que son privativas y generalmente usadas en Windows.
+1, totalmente de acuerdo.
|
|
|
En línea
|
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
Problema con funcion strcpy().
Programación C/C++
|
dark-heimdall
|
1
|
5,018
|
19 Febrero 2011, 06:36 am
por dark-heimdall
|
|
|
problema con uso de strcpy
Programación C/C++
|
m@o_614
|
2
|
2,810
|
19 Diciembre 2011, 18:37 pm
por m@o_614
|
|
|
strcpy entre char
Programación C/C++
|
Jupiter34
|
5
|
2,645
|
1 Noviembre 2012, 03:44 am
por BatchianoISpyxolo
|
|
|
strcpy en puntero matriz
Programación C/C++
|
psycho248
|
9
|
4,740
|
24 Junio 2014, 09:22 am
por eferion
|
|
|
ayuda con strcpy en kubuntu
Programación C/C++
|
Rom_Stom
|
6
|
2,999
|
15 Junio 2016, 03:47 am
por Rom_Stom
|
|