Error al crear punteros a estructuras.

Iniciado por NikNitro!, 5 Marzo 2015, 15:53 PM

0 Miembros y 1 Visitante están viendo este tema.

NikNitro!

Buenas. Pretendo recordar más o menos cómo se trabaja en C, pero llevo tiempo sin tocarlo.
He hecho una estructura de un LinkedArray de una vieja práctica que tenía por ahí, pero la función crear creo que la tengo mal.
Ésta función tendría que crear el LinkedArray con todos los elementos con valor 0, tamaño tam (todos el mismo) y puntero al siguiente.
Pues si creo uno y justo después lo muestro me pone tal que así:
{0, 1966492712, 1966492712, 1966492712, 1966492712}

Tiene pinta de que el primero me lo hace bien, pero cuando entra al for usa punteros a la misma zona de memoria, pero esa parte la estoy haciendo sin punteros, por lo que no entiendo qué ocurre.
Espero me ayudeis.

Os paso el .h:

/*
* File:   main.h
* Author: NikNitro
*
* Created on 3 de marzo de 2015, 19:38
*/

#ifndef MAIN_H
#define MAIN_H

typedef struct Array* Primero;
struct Array {
    int valor;
    int tam;
    Primero* sig;
};

void Crear(Primero* primero, int n);
void Destruir(Primero* primero);
void Obtener(Primero primero, int index, int *ok, int *valor);
void Cambiar(Primero* primero, int index, int valor);
void Mostrar(Primero primero);


#endif /* MAIN_H */




Y el .c


/*
* File:   main.c
* Author: NikNitro
*
* Created on 3 de marzo de 2015, 19:37
*/

#include <stdio.h>
#include <stdlib.h>
#include "main.h"

/*
*
*/

void Crear(Primero* primero, int n) {
     *primero = (Primero)malloc(sizeof(struct Array));
     (*primero)->tam = n;
     (*primero)->valor = 0;
     (*primero)->sig = NULL;
     Primero *ant = primero;
     int i;
     for(i=1; i<n; i++) {
         Primero nuevo;
//         (*nuevo) = (Primero)malloc(sizeof(struct Array));
         nuevo->valor=0;
         nuevo->tam = (*primero)->tam;
         nuevo->sig = NULL;
         (*ant)->sig = &nuevo;
         ant = (*ant)->sig;
     }
     
}
void Destruir(Primero* primero) {
    Primero ptr;
    while (*primero != NULL) {
        ptr=*(*primero)->sig;
        free((void *)*primero);
        *primero=ptr;
    }
}
void Obtener(Primero primero, int index, int *ok, int *valor) {
   
    if((*valor)<primero->tam) {
    int i;
    Primero aux = primero;
    for(i = 0; i < index; i++) {
        aux = *(aux->sig);
    }
    (*valor)=aux->valor;
    (*ok) = 1;
    } else {
        (*ok) = 0;
    }
}
void Cambiar(Primero* primero, int index, int valor) {
    int i;
    Primero *aux = primero;
    for(i = 0; i < valor; i++) {
        aux = (*aux)->sig;
        printf("%d\n", (*aux)->valor);
        fflush(stdout);
    }
    (*aux)->valor = valor;
   
}
void Mostrar(Primero primero) {
    int ultimo = primero->tam;
    int i;
    printf("{");
    for(i=0; i < ultimo-1; i++) {
        printf("%d, ", primero->valor);
    fflush(stdout);
        primero = *(primero->sig);
    }
    printf("%d}", primero->valor);
    fflush(stdout);
}

int main() {
    printf("Vamos a crear un array\n");
    fflush(stdout);
    Primero p;
    Crear(&p, 5);
//   int ok;
//   int valor;
//    Obtener(p, 3, &ok, &valor);
//    printf("%d", valor);
//   fflush(stdout);
//    Cambiar(&p, 2, 1);
    Mostrar(p);
    return (EXIT_SUCCESS);
}




Gracias por adelantado gente.

Saludos ;)

eferion

//         (*nuevo) = (Primero)malloc(sizeof(struct Array));

Debería ser

         nuevo = (Primero)malloc(sizeof(struct Array));

Si tienes esa línea comentada no se va a reservar memoria para los elementos que siguen al primero y eso solo puede resultar desastroso para tu programa.

Por otro lado, "Primero" no parece un nombre demasiado apropiado para un alias de "puntero a estructura".

Código complicado sin necesidad:

struct Array {
   int valor;
   int tam;
   Primero* sig;
};


"Primero", como hemos dicho, es un puntero. Dado que no es necesario que "sig" sea un puntero doble, se puede dejar únicamente como "Primero sig". Lo de "Primero" lo voy a respestar, aunque insisto que no es un nombre del que debas estar orgulloso :)

Primero *ant = primero;
    int i;
    for(i=1; i<n; i++) {
        Primero nuevo;
         (*nuevo) = (Primero)malloc(sizeof(struct Array));
        nuevo->valor=0;
        nuevo->tam = (*primero)->tam;
        nuevo->sig = NULL;
        (*ant)->sig = &nuevo;
        ant = (*ant)->sig;
    }


Otro puntero doble "ant" innecesario. Si le quitamos ese doble puntero el código queda más legible:

Primero ant = *primero;
    int i;
    for(i=1; i<n; i++) {
        Primero nuevo = (Primero)malloc(sizeof(struct Array));
        nuevo->valor=0;
        nuevo->tam = (*primero)->tam;
        nuevo->sig = NULL;
        ant->sig = nuevo;
        ant = ant->sig; // o ant = nuevo, como prefieras
    }



NikNitro!

Muchas gracias eferion :)
Ya va todo perfecto :)

Lo de "Primero" era el nombre que venía en la práctica xD
Lo de los punteros a punteros si ha sido cosa mia que me lié.

Saludos y gracias de nuevo;)