problemas con punteros

Iniciado por m@o_614, 4 Enero 2012, 20:15 PM

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

m@o_614

tengo un problema con este codigo que me tiene que ingresar un maximo de 20 registros con listas enlazadas, no se si lo estoy haciendo bien :rolleyes: no se si tengo que definir un nuevo tipo, algo asi como :

ingreso ingresos, y despues pasarle el apuntador ingreso*pIngreso y pasarle la direccion pIngreso=&ingresos :o

#include <stdio.h>
#include <stdlib.h>//funcion malloc()
#include <conio.h> // funcion getch()
#include <string.h> // funcion strcpy()
#define  MAX_REG 20 //Define el maximo numero de registros

// Primero definimos los tipos
typedef struct registro1
{
    char concepto[30+1];
    char RFC[21+1];
    float monto;
    int mes;
    struct registro1* sig;

}ingreso;

int introduceRegistro(ingreso *pIngreso);//le pasamos el puntero original de la lista

int main()
{
    ingreso *pIngreso;
    printf("\nIngresa los datos del registro \n");
    introduceRegistro(pIngreso);//Aqui todavia no estoy segura de ponerle el ampersand, porque me marca un warning:passing arg 1 of `introduceRegistro´ from incompatible pointer type

    getch();
    return 0;
}

int introduceRegistro(ingreso *pIngreso)
{
    int i;
    for(i=0,pIngreso->sig==NULL;i<MAX_REG;i++,pIngreso=pIngreso->sig)
    {
        pIngreso=(ingreso*)malloc(sizeof(ingreso));//A todo puntero hay que asignarle memoria.
        printf("Concepto :");
        fflush(stdin);
        gets(pIngreso->concepto);
        printf("RFC :");
        fflush(stdin);
        gets(pIngreso->RFC);
        printf("Monto :");
        fflush(stdin);
        scanf("%f",&pIngreso->monto);
        printf("Mes :");
        fflush(stdin);
        scanf("%d",&pIngreso->mes);
    }
return 0;
}

_Enko

#1
No soy bueno con esto de C, pero me parece qeu tienes problema en el for

for(i=0,pIngreso->sig==NULL;i<MAX_REG;i++,pIngreso=pIngreso->sig)
{
       pIngreso=(ingreso*)malloc(sizeof(ingreso));//A todo puntero hay que asignarle memoria.

pIngreso=pIngreso->sig....

pIngreso->sig siempre vale NULL en tu codigo, no apunta a ningun lado nunca.
a lo sumo seria al reves.
Para que funcione el for, tendria que ser

 pIngreso->sig = pIngreso


No es la misma inicializacion para el primer elemento de la lista que para los siguientes, deberia ir fuera del bucle.

pIngreso=(ingreso*)malloc(sizeof(ingreso));
for(i=0; i<MAX_REG; i++)
    {
pIngreso->valores = etc...
//modificamos valores pIngreso

//reservamos espacio para el elemento siguiente
//y aprovechamos para enlazarlo en la lista
        pIngreso->sig =(ingreso*)malloc(sizeof(ingreso));
//al final del bucle
//asignamos el elemento siguiente al actual
//para volver a trabajar con el nuevo elemento
pIngreso = pIngreso->sig
     
    }


Gallu

Hola , he revisado y cambiado algunas cosas de tu código, míratelo y comentamos lo que no comprendas ...

Por cierto , por si están tentados a comentar el tema recursividad usada en el programa, no se molesten,  tengo bastante claros los pros y contras ... en este caso la use solo para el ejemplo


#include <stdio.h>
#include <stdlib.h>//funcion malloc()
//no debes usar nunca conio
//#include <conio.h> // funcion getch()
#include <string.h> // funcion strcpy()
#define  MAX_REG 2 //Define el maximo numero de registros

//limpia el buffer
#define LIMPIAR_BUFFER while(getchar() != '\n')

// Primero definimos los tipos
typedef struct registro1
{
    char concepto[30+1];
    char RFC[21+1];
    float monto;
    int mes;
    struct registro1* sig;

}ingreso;

int introduceRegistro(ingreso **pIngreso);//le pasamos el puntero original de la lista

//agrega un elemento a la lista
void addIngreso(ingreso **pIngreso , ingreso *aux );

//imprime el campo concepto de todos los elementos en la lista
void imprimeConcepto(ingreso *pIngreso);


int main()
{
    ingreso *pIngreso = NULL;
    printf("\nIngresa los datos del registro \n");
    introduceRegistro(&pIngreso);

    printf("presiona una tecla para continuar...\n") ;
    getchar();
    return 0;
}

void addIngreso(ingreso **pIngreso , ingreso *aux ){
if(*pIngreso == NULL){
*pIngreso = aux;
}else{
//llamamos recursivamente a la función
addIngreso(&((*pIngreso)->sig) , aux);
}
}

void imprimeConcepto(ingreso *pIngreso){
if(pIngreso != NULL){
printf("%s \n", pIngreso->concepto);
imprimeConcepto(pIngreso->sig);
}
}

int introduceRegistro(ingreso **pIngreso)
{
    int i;
    //lo usamos para ir agregando la información
    ingreso *aux;

    for(i=0 ;  i<MAX_REG ; i++ ){   
        aux = (ingreso*)malloc(sizeof(ingreso));//A todo puntero hay que asignarle memoria.

        printf("Concepto :");
        gets(aux->concepto);

        printf("RFC :");
        gets(aux->RFC);     

        printf("Monto :");
        scanf("%f",&aux->monto);
        LIMPIAR_BUFFER;       

        printf("Mes :");
        scanf("%d",&aux->mes);
LIMPIAR_BUFFER;
       
        //lo agregamos a la lista
        addIngreso(pIngreso, aux);
    }
   
    printf("Los valores del campo concepto de la lista de ingresos son : \n");
   //mostramos el "concepto" de todos los campos
   imprimeConcepto(*pIngreso);

return 0;
}


Saludos
Nadie alcanza la meta con un solo intento, ni perfecciona la vida con una sola rectificación, ni alcanza altura con un solo vuelo.

BlackZeroX

#3
Modifique un poco tu codigo...

A por cierto conio.h es solo bajo Windows... pero tu decide si la quieres o no usar.



#include <stdio.h>
#include <stdlib.h>//funcion malloc()
#include <string.h> // funcion strcpy()

#define MAX_REG 20 //Define el maximo numero de registros
#define MAX_CONCEPTO 30+1
#define MAX_RFC 21+1


// Primero definimos los tipos
typedef struct registro1
{
    char concepto[MAX_CONCEPTO];
    char RFC[MAX_RFC];
    float monto;
    int mes;
    struct registro1* next;

}INGRESO,   //  Tipo..
*LPINGRESO; //  Puntero a un Tipo en lugarde esrbir *INGRESO se escribe LPINGRESO

LPINGRESO introduceRegistro(LPINGRESO lpIngreso, int* iCount, int iMaxReg, int addIn);//le pasamos el puntero original de la lista
int releaseIngresos(LPINGRESO lpIngreso);
LPINGRESO getLastIngreso(LPINGRESO lpIngreso);

int main()
{
    LPINGRESO lpIngreso = NULL;
    printf("\nIngresa los datos del registro \n");

    lpIngreso = introduceRegistro(lpIngreso,    //  Empesamos desde este registro... obviamente como es NULL creara un nuevo registro...
                                  NULL,
                                  MAX_REG,
                                  1);
    printf("%d\n", releaseIngresos(lpIngreso));
    getchar();

    return EXIT_SUCCESS;
}

//  Libera TODOS LOS NODOS siguientes de INGRESO...
int releaseIngresos(LPINGRESO lpIngreso)
{
    int iRet = 0;

    if (lpIngreso)
    {
        iRet = 1 + releaseIngresos(lpIngreso->next);    //  Liberamos los hijos...
        free(lpIngreso);                            //  Liberamos...
    }
    return iRet;
}

//  Retorna el ultimo registro...
LPINGRESO getLastIngreso(LPINGRESO lpIngreso)
{
    if (lpIngreso)
        while (lpIngreso->next)
            lpIngreso = lpIngreso->next;
    return lpIngreso;
}

/// La función va a retornar un LPINGRESO al 1er elemento INGRESO...
LPINGRESO introduceRegistro(LPINGRESO lpIngreso,    //  Lista desde donde se empesara a crear...
                            int* iCount,            //  Ouput Retorna la cantidad de registros creados...
                            int iMaxReg,            //  MAXIMO de registros a crear...
                            int addIn)              //  Si lpIngreso->next apunta a otro registro, los registros a crear se deben insertarse:
                                                    //  -1 Creamos lo registros entre lpIngreso y lpIngreso->next...
                                                    //  0 Eliminar TODOS apartir de lpIngreso->next e insertar los nuevos.
                                                    //  1 Inserta los registros al final al final de la lista.
                                                    //  Se ignora este parametro si lpIngreso es NULL.
{
    int i = 0;
    LPINGRESO lpNewIngreso = NULL;
    LPINGRESO lpNextStaticIngreso = NULL;
    LPINGRESO lpFirtsIngreso = lpIngreso;

    /// Si lpIngreso ya tiene otros registros enlazados podemos hacer tres cosas
    if (lpIngreso)
        switch(addIn)
        {
            case -1:    //  Agregamos los nuevos seguido a lpIngreso pero antes de lpIngreso->next
                lpNextStaticIngreso = lpIngreso->next;
                break;

            case 0:     //  Eliminamos TODOs lo registros desde lpIngreso->next...
                releaseIngresos(lpIngreso->next);
                break;

            default:    //  Buscamos el ultimo de la lista y empesamos a agregarlos apartir de este.
                lpIngreso = getLastIngreso(lpIngreso);
                break;
        }

    for(i = 0
        //, lpIngreso->next == NULL ->> No tiene caso comprobar con NULL... creo que querias asignarle NULL, ¿no?.
        ;i < iMaxReg;  //  Cantidad de registros...
        i++)           //  Contador creciente en 1.
    {
        lpNewIngreso = (LPINGRESO)malloc(sizeof(INGRESO));

        if (!lpNewIngreso)  //  Se reservo la memoria deseada?...
            break;  //  Salimos del for()...

        memset(lpNewIngreso, 0, sizeof(INGRESO));   //  Limpiamos el bloque de memoria...

        if (!lpFirtsIngreso)
            lpFirtsIngreso = lpNewIngreso;

        //  Enlazamos con el anterior...
        if (lpIngreso)
            lpIngreso->next = lpNewIngreso;

        lpIngreso = lpNewIngreso;

        /// El llenado de datos se puede hacer despues de haber creado los elementos...
        /*
        fprintf(stdout, "Concepto:\n");
        fgets(lpIngreso->concepto, MAX_CONCEPTO - 1, stdin);    //  Hay que leer solo la longitud requerida...

        fprintf(stdout, "RFC:\n");
        fgets(lpIngreso->concepto, MAX_RFC - 1, stdin);    //  Hay que leer solo la longitud requerida...

        fprintf(stdout, "Monto:\n");
        scanf("%f", &lpIngreso->monto);

        fprintf(stdout, "Mes:\n");
        scanf("%d", &lpIngreso->mes);
        */
    }

    if (iCount)
        (*iCount) = i;

    lpIngreso->next = lpNextStaticIngreso;

    return lpFirtsIngreso;
}



Dulces Lunas!¡.
The Dark Shadow is my passion.

m@o_614

no entiendo por que usas doble puntero  :o ????

Xandrete

¡Hola m@o_614 (y al resto  ;D)!

Yo me imagino que utiliza dobles punteros porque en C no se puede pasar parámetros por referencia con el & a las funciones (eso es algo nuevo de C++), así que para lograr lo mismo, lo que se hace es pasar un puntero al dato que querías que se modificara dentro de la función (de hecho, eso es lo que hace internamente C++). Como has dicho lo de pasar el parámetro con el ampersand (&) en los comentarios de tu código, yo me he imaginado que el código era para C++, pero luego veo el resto y compruebo que es un código típicamente C, así que no sé interpretar muy bien si lo quieres para C estricto o si se pueden incorporar novedades C++.

Si estás programando en C++ tienes cositas para facilitarte la vida. Por ejemplo, en lugar de usar malloc, puedes usar el operador new (y te ahorras incluir una librería). Por otro lado, puedes usar la librería string de C++ en lugar de la librería de C. Una de sus principales ventajas es que te permite usar un objeto string que te evita lidiar con tamaños de arrays y demás "basura" (lo digo cariñosamente  ;D) que te aleja de lo que es la solución al problema en sí mismo. Por otro lado, te recomendaría restringirte a la librería estándar para estas cosas (lo digo por lo de conio). Y también te diría que no usaras fflush para limpiar el buffer de entrada (explicación de estos dos últimos consejos en uno de los post con chincheta de este mismo foro: http://foro.elhacker.net/programacion_cc/lo_que_no_hay_que_hacer_en_cc_nivel_basico-t277729.0.html). De todas formas, eso es harina de otro costal. Lo que importa aquí son los punteros, ¿no  :D?

Yo también he hecho mi propia versión del programa (pero en C++):

Código (cpp) [Seleccionar]
#include <iostream>
#include <string>
#define  MAX_REG 20
using namespace std;

struct Ingreso {
string concepto;
string RFC;
float monto;
int mes;
Ingreso* sig;

};

void rellenarDatos(Ingreso* ing) {
cout << "Concepto: ";
cin >> ing->concepto;
cout << "RFC: ";
cin >> ing->RFC;
cout << "Monto: ";
cin >> ing->monto;
cout << "Mes: ";
cin >> ing->mes;
}

Ingreso* agregarIngreso(Ingreso* ultimoIngreso) {
Ingreso* siguienteIngreso;
if (ultimoIngreso == NULL) siguienteIngreso = new Ingreso;
else siguienteIngreso = ultimoIngreso->sig = new Ingreso;
rellenarDatos(siguienteIngreso);
return siguienteIngreso;
}

Ingreso* introduceRegistro() {
int i;
Ingreso* pIngreso;
Ingreso* ultimoIngreso;
pIngreso = ultimoIngreso = agregarIngreso(NULL);
for(i=1;i<MAX_REG;++i)
ultimoIngreso = agregarIngreso(ultimoIngreso);
ultimoIngreso->sig = NULL;
return pIngreso;
}

int main() {
cout << "Ingresa los datos del registro" << endl;
Ingreso* pIngreso = introduceRegistro();
/* ... */
}


No me preocupado por el tema de la entrada de datos mucho. Para controlar el tema del buffer de entrada y estas "tonterías" (cariñosamente otra vez) sólo habría que tocar la rutina rellenarDatos.

Por cierto, BlackZeroX, "peaso" código, ¿no  :rolleyes:?

¡Saludacos!