Dudilla estúpida (C)

zildjian

Hola! Es una tontería pero ahora mismo no lo recuerdo bien. En un main declaro una serie de variables que le paso como parámetro a una función void. La función void efectúa cambios sobre estas variables pero sin embargo, al ir a seguir "jugando" con ellas en el main no tienen el valor modificado, si no que tienen el original. ¿Cómo soluciono esto?

Angel89

pon el codigo, o un codigo ejemplo.

NeB1

tienes que pasar el puntero:

//Declaramos la función, con dos punteros como variables
void funcionMia(int *a, int *b);

//main function
main(){

  int hola, adios;
  funcionMia(*hola, *adios)

}

void funcionMia(int *a, int *b){

  &a=1+8;
  &b=a-4;

}

era algo así, no?

si no me falla la memoria, le pasas la direccion de a y de b (por eso *a y *b) y en la función como esas variables son direcciones de memoria, le ponemos el "&" delante para decir "Donde apunta la dirección de 'a' escribe esto"

Angel89

si ,creo que esta bien, se llama pasar por referencia o por valor si quieres mantener el valor o no..

Fr4nk0

Me parece que es al reves, es decir en la llamada a la funcion le pasas la direccion de la variable (&) y dentro de la funcion para cambiar el contenido es con el operador *.

    //Declaramos la función, con dos punteros como variables
    void funcionMia(int *a, int *b);
   
//main function main(){ int hola, adios; funcionMia(&hola, &adios) }
void funcionMia(int *a, int *b){
*a=1+8; *b=*a-4; //el contenido (*) de b será el contenido de a menos 4.
}

Otra opcion seria declarar las variables como punteros (int* hola, *adios) , con lo que lo único que variaría sería que la llamada a la funcion sería funcionMia(hola,adios) pero luego el acceso al contenido sería igual (con el *)

PD: Corregidme si me equivoco :P

Angel89

yo sin un compilador delante no se xD, siempre me e rallao si es de una forma u otra

Buffoncete

si es ANSI C es exactamente como ha puesto #5

para los mas puros, en su código no ha inicializado ni hola ni adios, así que tendrán basura en ANSI C, hay que inicializarlos antes. Y el main le falta un void delante xD

NeB1

#5 eso eso!!! q me he rallado! xDD

zildjian

Me sigo sin funcionar... :( En el main hago la llamada así (una variable entero y un puntero de carácteres, que por cierto, no se si se hará de la misma manera...)

lee_texto(&length, texto);

Como véis, en texto no le pongo nada porque ya es un puntero de chars.

Y la en la función:

void lee_texto(int * length, char * texto){
    /* Declaramos variables y auxiliares */
    int i = 0, j = 0, size = 100;
    char aux;

/* Abrimos el archivo donde se encuentra el texto cifrado */
FILE *f;
f = fopen("archivodetexto.txt", "r");

if(f==NULL){
    perror("No se puede abrir el archivo. Saliendo del programa!");
    exit(1);
}

/* Reservamos memoria para el vector texto */
texto = (char *)malloc( size*sizeof(char) );

/* Leemos los caracteres del archivo (todos) */
*length = -1;
while(aux!=EOF){
    aux = getc(f);

    if(i>=100){
        texto = (char *)realloc( texto, size++ );
    }

    texto[i] = aux;
    i++;
    *length++;  // Indica la longitud del vector de texto
}

printf("%d\n", length);
}

O sea, lo que me falla es únicamente el vector :(

Saludos.

Buffoncete

Te comento fallos que cometes, delegas que el vector te lo reserve una función para luego retornarlo, esto está mal.

/* Reservamos memoria para el vector texto */
texto = (char *)malloc( size*sizeof(char) ); 

el malloc tienes que hacerlo en la función que llama a lee_texto, si lee_texto descubre que necesita 25 MB de espacio para texto, debería retornar un error y en length poner la longitud necesaria y tu desde la otra función, hacer el malloc y volver a llamar, por qué ?

Primero, por que para que te funcione un malloc dentro de una función que pasas como parámetro un puntero, tienes que pasar un doble puntero, por que lo que haces es, la dirección a la que apunta el vector que pasas le generas una nuevo espacio en memoria que apuntará a la pila actual, no a la posición de memoria que tiene la función anterior, si has estudiado ensamblador entenderás que te estoy diciendo.

Si lo quieres seguir haciendo así, craso error, utiliza char ** texto en la llamada.

EDITO: ahora sigo escribiendo xD

tu cabecera quedará así:

void lee_texto(int * length, char ** texto){ 

Por otro lado y aunque me repita, o no, llevo muchos edits, nunca tienes que delegar a una función que reserve memoria por ti, pongamos que lee_texto está en un servidor o es una llamada de un webservice que trabaja en memoria en Big Endian, y tu trabajas en tu ordenador en little endian, si delegas la responsabilidad al webservice cuando retomes el resultado lo leerás mal y tendrás que reformatearlo.

Además, ponte que trabajas en la misma máquina, y esa llamada la tiene una DLL del sistema o un .SO, si la .DLL o el .SO o le .dylib, no nos vamos a poner quisquillosos xD reserva memoria, la está reservando en su zona de trabajo, ahora te hago la pregunta, quien debe liberarla ? tu aplicación que no tiene acceso real a esa zona o el .SO, .DLL o .DYLIB ?

Mi consejo es el siguiente.

char * texto = NULL;
int length = 0;
lee_texto(&length, texto);
texto = (char *)calloc(length,sizeof(char));
lee_texto(&length, texto);

Así la memoria la utilizas tú, quizá en un futuro cambias la aplicación de lugar o los sistemas operativos cambian su modus operandi y tu aplicación seguirá funcionando igual ;)

Ah, y queda claro que tú problema es por no poner en la llamada de la función char ** texto

zildjian

Pero es que si la función la declaro así:

void lee_texto(int * length, char **texto)

después me peta con los malloc xD

Buffoncete

por que el malloc se lo tienes que hacer a *texto :P

NeB1

#12 jodidos punteros de C

Buffoncete

si es lo mejor para ganar eficiencia en cuanto a velocidad de procesado y espacio de memoria ;)

zildjian

Otra preguntita:

Tengo declarado el siguiente vector:

char *buffer[]={"palabr", "palabra"};

Y tengo la siguiente función:

char* strgen(int i, char string[]){
    char aux[6];
    int j;
    for(j=i;j<i+6;j++){
        aux[j-i]=string[j];
    }
    return aux;
}

Y desde el main, hago la siguiente llamada:

buffer[0] = strgen(i, string);

Donde i es un iterador. Pero al compilar, aparece el siguiente chachi-error:
main.c: En la función ‘main’:
main.c:46: aviso: la asignación crea un puntero desde un entero sin una conversión
op.c: En la función ‘strgen’:
op.c:63: aviso: la devolución crea un entero desde un puntero sin una conversión
op.c:63: aviso: la función devuelve la dirección de una variable local

Buffoncete

fuera de los otros errores que no voy a comentar:

op.c:63: aviso: la función devuelve la dirección de una variable local

deja de guardar memoria en funciones y luego retornarlas tio xD programa bien aunque sea un código pequeño.

los motivos ya te los he puesto arriba.

Usuarios habituales

  • Buffoncete
  • zildjian
  • NeB1
  • Angel89
  • Fr4nk0