Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: HardForo en 17 Abril 2016, 00:28 am



Título: Problema al pasar char* como parametro
Publicado por: HardForo en 17 Abril 2016, 00:28 am
Gente:

   Estaba leyendo como es calculo de longitud de un array (http://hardforo.com/thread-174.html) y estaba seguro de que podia implementar una funcion del tipo strlen() para punteros a char pero me encontré con un problema inesperado:

Código
  1. #include <stdio.h>
  2. #include <string.h>
  3.  
  4. // longitud de un char*
  5. int charlen(char* x){
  6. return sizeof(x) / sizeof(x[0]);
  7. }
  8.  
  9. int main(void){
  10.  
  11. int i;
  12.  
  13. char x[]={'H','A','R','D','F','O','R','O'};
  14. const char *y = "HARDFORO";
  15.  
  16. for (i=0;i<sizeof(x) / sizeof(x[0]);i++)
  17. printf("%c",x[i]); // HARDFORO
  18.  
  19. printf("\n\n",x[i]);
  20.  
  21. for (i=0;i<strlen(y);i++)
  22. printf("%c",y[i]); // HARDFORO
  23.  
  24. }
  25.  

Si en vez de hacer en el main() la division sizeof(x) / sizeof(x[0]) la hago en una funcion, el resultado me varía (me da 4 y me temo sea basura y pueda dar otro valor)

Por qué ?



Código
  1. for (i=0;i<charlen(x);i++)
  2. printf("%c",x[i]); // HARD  <-- error
  3.  


Título: Re: Problema al pasar char* como parametro
Publicado por: ivancea96 en 17 Abril 2016, 00:36 am
En C/C++ hay 2 tipos de arrays: los estáticos y los dinámicos, por así decirlo.
"char str[ 10 ]" sería  estático, es una variable de 10 bytes,
"char *str" sería dinámico, y realmente no es un array, sino un puntero a char.

Cuando le pasas un array estatico a la función, lo interpreta como simplemente un puntero. El tamaño de un puntero es de 4 bytes, y el tamaño de un char es de 1 byte (por lo general).
Así pues, 4/1 = 4. Ahí tu resultado, totalmente real.

Solo hay 2 formas reales de saber el tamaño de una cadena: o pasándoselo a las funciones (evidentemente, funciona siempre), o contando caracteres hasta encontrar un caracter nulo ('\0', funciona solo con cadenas de texto, no para binarias).
strlen lo que hace es contar hasta el caracter nulo.


Título: Re: Problema al pasar char* como parametro
Publicado por: MAFUS en 17 Abril 2016, 00:52 am
Un array no es un puntero. Son dos tipos de objetos diferentes. C sabe el tamaño que tiene un array pues se lo has indicado pero un puntero puede apuntar a cualquier cosa y no hay información sobre lo que guarda. Por tanto el tamaño de un puntero tan solo te devolverá el tamaño de la palabra del procesador.

Así mientras tengas la declaración del array a la vista de sizeof éste sabrá que tamaño tiene, en cuánto lo referencies con un puntero habrás terminado con ese dato.

¿Qué quiere decir eso?
Si declaras el array de forma global, fuera de toda función, a partir de ese momento todo el programa conocerá el tamaño del array.
Si declaras el array de forma local, dentro de una función, únicamente dentro de esa función se sabrá el tamaño de ese array.


Título: Re: Problema al pasar char* como parametro
Publicado por: HardForo en 17 Abril 2016, 01:07 am
Les agradezco a ambos... en cierto punto entienden lo mismo... pero yo entiendo menos y aun menos cuando pruebo lo que interpreto  :laugh:

Código
  1. #include <stdio.h>
  2. #include <string.h>
  3.  
  4.  
  5. int charlen(char* x){
  6. return sizeof(x) / sizeof(x[0]);
  7. }
  8.  
  9.  
  10. // Global variables
  11.  
  12. char x[]={'H','A','R','D','F','O','R','O'};
  13. const char *y = "HARDFORO";
  14.  
  15.  
  16. int main(void){
  17.  
  18. int i;
  19.  
  20.  
  21. for (i=0;i<charlen(x);i++)
  22. printf("%c",x[i]); // HARD <--- 4
  23.  
  24. printf("\n\n",x[i]);
  25.  
  26. for (i=0;i<strlen(y);i++)
  27. printf("%c",y[i]); // HARDFORO
  28.  
  29. }
  30.  

<-- los declaré globalmente

Lo que esta clarisimo es que pueden explicar ese 4 pero sera que me ayudan a que como funcion pueda determinar el tamaño del char* ?

Quiero aclarar que si uso strlen() obtengo basura:

Código
  1. for (i=0;i<strlen(x);i++)
  2. printf("%c",x[i]); // HARDFORO+á@
  3.  

<-- Hay basura al final ya que me reporta 11 de longitud


Título: Re: Problema al pasar char* como parametro
Publicado por: ivancea96 en 17 Abril 2016, 01:18 am
Como digo, strlen solo funciona en cadenas que terminen en '\0'.
Este array: "char x[]={'H','A','R','D','F','O','R','O'};" no termina en caracter nulo, así que strlen seguirá sumando caracteres hasta encontrar uno.

Cuando pones: char x[] = "HARDFORO", esa cadena sí termina en caracter nulo. Las cadenas "" en C terminan en caracter nulo, aunque no se lo digas explícitamente.

Si vas a trabajar con caracteres como texto, evita inicializar con "{}".


Título: Re: Problema al pasar char* como parametro
Publicado por: MAFUS en 17 Abril 2016, 01:19 am
En tu función charlen has ocultado identificador x que nombra el array, por lo que dentro de la función éste ya no se ve.
Realmente lo que te he dicho es falso pues el array x en el momento de la definición de la función no existe así que es imposible que C sepa el tamaño de éste.
Para que el programa funcione debes hacer los siguientes cambios.

Código
  1. #include <stdio.h>
  2. #include <string.h>
  3.  
  4. // Global variables
  5.  
  6. char x[]={'H','A','R','D','F','O','R','O'};
  7. const char *y = "HARDFORO";
  8.  
  9. int charlen(){
  10. return sizeof(x) / sizeof(x[0]);
  11. }
  12.  
  13. int main(void){
  14.  
  15. int i;
  16.  
  17.  
  18. for (i=0;i<charlen();i++)
  19. printf("%c",x[i]); // HARDFORO
  20.  
  21.    putchar('\n');
  22.  
  23. for (i=0;i<strlen(y);i++)
  24. printf("%c",y[i]); // HARDFORO
  25. }


Título: Re: Problema al pasar char* como parametro
Publicado por: HardForo en 17 Abril 2016, 01:30 am
@ivancea96: lo que dices tiene mucho sentido, gracias  ;D


@MAFUS: pero entonces esa funcion no seria muy util que digamos ? o sea no acepta parametros ?

Estoy sorprendido de que no se pueda abstraer un poco mas  >:(

Bueno... dejo planteado el problema por si se les ocurre algo y agradezco las explicaciones (a ambos)


En un acto de desespero...... he intentado usar punteros dobles pero fallo en algo (como raro yo) xD

Código
  1. #include <stdio.h>
  2.  
  3. // longitud de un char*
  4. int charlen(char** x){
  5. return sizeof(*x) / sizeof(*x[0]);
  6. }
  7.  
  8. int main(void){
  9.  
  10. int i;
  11.  
  12. char x[]={'H','A','R','D','F','O','R','O'};
  13.  
  14. for (i=0;i<charlen(&x);i++)
  15. printf("%c",x[i]);
  16.  
  17. }
  18.  

Lo podran mirar ? gracias


Título: Re: Problema al pasar char* como parametro
Publicado por: ivancea96 en 17 Abril 2016, 01:41 am
Ya que C es programación estructurada, la forma de abstraerlo sería crear una estructura:
Código
  1. typedef struct String{
  2.    char* str;
  3.    unsigned int size;
  4. } String;
  5.  
  6. String makeString(char* data, unsigned int size){
  7.    String s;
  8.    s.size = size;
  9.    if(size==0)
  10.        s.size = strlen(data); // Para cadenas de texto
  11.    int i = 0;
  12.    for(; i<s.size; i++)
  13.        s.str[i] = data[i];
  14.    return s;
  15. }
  16.  
  17. // ...

Y luego haces todas las funciones que quieras para manejarlo.
Si programas C++, esto lo tendrás muy fácil con clases. De hecho, ya está en la librería estándar de C++ la clase "string".


Título: Re: Problema al pasar char* como parametro
Publicado por: HardForo en 17 Abril 2016, 01:46 am
Gracias Ivan, entonces supongo que o hago in situ el sizeof(x)/sizeof(x[0]) o me se el valor por anticipado o uso strings :)

Gracias


Título: Re: Problema al pasar char* como parametro
Publicado por: ivancea96 en 17 Abril 2016, 01:49 am
Gracias Ivan, entonces supongo que o hago inline el sizeof(x)/sizeof(x[0]) o me se el valor por anticipado o uso strings :)

Gracias

strlen es una opción, la más común y útil para texto, siempre que uses la inicialización vía " " y no con { ... }.


Título: Re: Problema al pasar char* como parametro
Publicado por: HardForo en 17 Abril 2016, 01:56 am
Gracias otra vez.............. 

Aprovecho para reflexionar: por algo se tuvieron que inventar los "strings" con un terminador en \0 (es concistente con que no es muy practico hacer un coiciente de sizeof(s))


Título: Re: Problema al pasar char* como parametro
Publicado por: MAFUS en 17 Abril 2016, 02:00 am
De nuevo te repito: Una vez que usas un puntero C pierde la pista al dato al que apunta. Tal y como te dice ivancea96 puedes crearte un tipo de dato que contenga un array y su tamaño o creas una función como la siguiente:

Código
  1. int arraylen(size_t type_length, size_t array_length) {
  2.    return array_length / type_length;
  3. }

Y lo llamas así:

Código
  1. int array[] = {1, 2, 3, 4, 5};
  2. int n = arraylen(sizeof(int), sizeof array);
  3.  


Título: Re: Problema al pasar char* como parametro
Publicado por: HardForo en 17 Abril 2016, 02:08 am
No le demos mas vueltas, esa funcion solo hace una division  :xD

Ya les he comprendido........ gracias a los dos