Problema al pasar char* como parametro

Iniciado por HardForo, 17 Abril 2016, 00:28 AM

0 Miembros y 2 Visitantes están viendo este tema.

HardForo

Gente:

  Estaba leyendo como es calculo de longitud de un array y estaba seguro de que podia implementar una funcion del tipo strlen() para punteros a char pero me encontré con un problema inesperado:


#include <stdio.h>
#include <string.h>

// longitud de un char*
int charlen(char* x){
return sizeof(x) / sizeof(x[0]);
}

int main(void){

int i;

char x[]={'H','A','R','D','F','O','R','O'};
const char *y = "HARDFORO";

for (i=0;i<sizeof(x) / sizeof(x[0]);i++)
printf("%c",x[i]); // HARDFORO

printf("\n\n",x[i]);

for (i=0;i<strlen(y);i++)
printf("%c",y[i]); // HARDFORO

}


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é ?



for (i=0;i<charlen(x);i++)
printf("%c",x[i]); // HARD  <-- error
HardForo:  foro de Hardware y programación

Se buscan Mods y colaboradores *

ivancea96

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.

MAFUS

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.

HardForo

#3
Les agradezco a ambos... en cierto punto entienden lo mismo... pero yo entiendo menos y aun menos cuando pruebo lo que interpreto  :laugh:


#include <stdio.h>
#include <string.h>


int charlen(char* x){
return sizeof(x) / sizeof(x[0]);
}


// Global variables

char x[]={'H','A','R','D','F','O','R','O'};
const char *y = "HARDFORO";


int main(void){

int i;


for (i=0;i<charlen(x);i++)
printf("%c",x[i]); // HARD <--- 4

printf("\n\n",x[i]);

for (i=0;i<strlen(y);i++)
printf("%c",y[i]); // HARDFORO

}


<-- 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:


for (i=0;i<strlen(x);i++)
printf("%c",x[i]); // HARDFORO+á@


<-- Hay basura al final ya que me reporta 11 de longitud
HardForo:  foro de Hardware y programación

Se buscan Mods y colaboradores *

ivancea96

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 "{}".

MAFUS

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.


#include <stdio.h>
#include <string.h>

// Global variables

char x[]={'H','A','R','D','F','O','R','O'};
const char *y = "HARDFORO";

int charlen(){
return sizeof(x) / sizeof(x[0]);
}

int main(void){

int i;


for (i=0;i<charlen();i++)
printf("%c",x[i]); // HARDFORO
   
    putchar('\n');

for (i=0;i<strlen(y);i++)
printf("%c",y[i]); // HARDFORO
}

HardForo

#6
@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

#include <stdio.h>

// longitud de un char*
int charlen(char** x){
return sizeof(*x) / sizeof(*x[0]);
}

int main(void){

int i;

char x[]={'H','A','R','D','F','O','R','O'};

for (i=0;i<charlen(&x);i++)
printf("%c",x[i]);

}


Lo podran mirar ? gracias
HardForo:  foro de Hardware y programación

Se buscan Mods y colaboradores *

ivancea96

Ya que C es programación estructurada, la forma de abstraerlo sería crear una estructura:
typedef struct String{
    char* str;
    unsigned int size;
} String;

String makeString(char* data, unsigned int size){
    String s;
    s.size = size;
    if(size==0)
        s.size = strlen(data); // Para cadenas de texto
    int i = 0;
    for(; i<s.size; i++)
        s.str[i] = data[i];
    return s;
}

// ...


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".

HardForo

#8
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
HardForo:  foro de Hardware y programación

Se buscan Mods y colaboradores *

ivancea96

Cita de: boctulus en 17 Abril 2016, 01:46 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 { ... }.