Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - MAFUS

#1281
Entiendo que el código que has pasado no se puede tocar más que para introducir la funcionalidad del DNI.
#1282
Muy bien, veo que lo has entendido.
Ahora recuerda que es mala práctica abusar de typedef, y más si typedef esconde detrás punteros. Debe usarse para esclarecer el código, no ofuscarlo. Muchas veces es mejor, para un tercero, saber que un tipo de dato es un puntero; a no ser que sea intención tuya una ocultación expresa de los interiores del tipo de dato en cuestión, simulando a lo que se hace con la programación orientada a objetos.
#1283
Son fallos básicos de punteros pero a los que se pierde rápidamente la pista cuándo no se está acostumbrado. Con práctica los irás solucionando.

Tienes razón al escribir
void push(listaPTR listp, int value)
pues necesitas variar la dirección contenida en lista si esta apunta a NULL, pero fallas cuándo escribes e = &listp;
por el hecho de que ahora e apunta a la dirección de listp.

*** Dando una vuelta de tuerca al tratamiento de la memoria en C ***
listp debe considerarse una variable local de la función push por lo que obtener su dirección no hará que apuntes a la lista original sino a una parte de la pila de la función a la que estás.
Lo que debes obtener es el valor que hay guardado en listp que será la dirección en la que se guarda la lista.
Sé que es complicado dicho así, pero si lo llegas a entender se acabarán los problemas con los punteros. Como regla nemotécnica piensa en que vas a sacar un asterisco a tu puntero. Algo así:
Tu tienes **listaPTR
Dentro tienes *lista
Como ves hay que quitarse un asterisco de encima para obtener *lista.
En el código
node *e
haces un puntero a node. Es lo mismo que hacer
lista e
ya que node * es lo mismo que lista.
Ahora viene cuando sacamos un asterisco **listaPTR. Para ello, durante la asignación cogemos ese asterisco, lo sacamos de **listaPTR y lo dejamos a su izquierda. En código queda así:
e = *list
Ahora los dos objetos son del mismo tipo y se respeta la igualdad.

Bien. Pasemos a los argumentos de llamada de la función push.
Hemos creado nuestra lista, l, y su tipo es *lista pero el argumento espera que le entreguemos la dirección de memoria donde se guarda ésta. Otra vez podemos hacer uso de una regla nemotécnica: debemos pensar que queremos incluir un asterisco a esa variable y para ello cogemos y, ni cortos ni perezosos, se lo escribimos a mano con el símbolo & a su izquierda. De hecho & parece como si quisiéramos escribir un asterisco de forma rápida y sin levantar el lápiz del papel.
En código queda así:

push(&l,20);

Así *lista con un asterisco más digievoluciona a **listaPTR.

Tu código funcional quedaría de la siguiente forma:
#include <stdlib.h>
#include <stdio.h>


typedef struct nodo_t {
    int value;
    struct nodo_t* next;
} node, *lista, **listaPTR;


lista new_node(int value){
    node * n = (node *) malloc(sizeof(node));
    n->value = value;
    n->next = NULL;
    return n;
}

lista new_lista(){
    return NULL;
}


void print_list(lista head){
    node *prev;

    prev =  head;
    while (prev)
    {
        printf("%d\n", prev->value);
        prev = prev->next;
    }
}


void push(listaPTR list, int value)
{
    node *e,*prev,*n;
    int v; /* v no se usa */

    // camino hasta el final de la list (poco eficiente, mejor tener puntero al final)
    e = *list;
    while (e){
        prev = e;
        e = e->next;
    }

    // creo nodo
    n = new_node(value);

    if (*list == NULL)
    {
        *list = n;
        //printf("Elem: %d\n",list->value);
        //printf("Elementos: %d\n",count(list));
    }
    else
        // inserto al final
        prev->next = n;
}


int main() {
    lista l = new_lista();
    push(&l,20);
    push(&l,40);
    print_list(l);
}
#1284
Programación C/C++ / Re: Cuadrado en c++
14 Abril 2016, 17:46 PM
Solución sencilla, en C, sin control de errores de entrada.

#include <stdio.h>

int main() {
   int x;
   int x2;
   char c;
   
   printf("Caracter a imprimir > ");
   c = getchar();
   printf("Tamaño del lado del cuadrado > ");
   scanf("%i", &x);
   
   x2 = x*x;
   
   while(x2--) {
       putchar(c);
       if(x2 % x == 0)
           putchar('\n');
   }

    return 0;
}
#1285
Muy buenas. Muchas gracias, me alegro que mis aportaciones te sirvan.

typedef, que supongo que no sabes que es, sirve para crear alias de tipos de datos. De forma simple
typedef int entero;
ahora escribir entero es como si escribieramos int por lo que
entero num;
es lo mismo que escribir
int num;

Del mismo modo se pueden crear datos de tipo puntero
typedef int *puntero_a_int
ahora puntero_a_int se ha convertido en un int *
por lo que el siguiente fragmento es válido

typedef int *puntero_a_int;
int a = 3;
puntero_a_int = &a;


Ahora al código
typedef struct nodo_t {
    int valor;
    struct nodo_t* siguiente;
} nodo, *pila;


lo que hace es crear un nodo básico en el empleo de listas y pilas:

struct nodo_t {
    int valor;
    struct nodo_t* siguiente;
}


Podría trabajar solo con eso, sustituyendo lo que en el código aparece como nodo por struct nodo_t y lista por struct nodo_t * pero creando esos dos alias el código queda más comprensible a simple vista.

Básicamente lista y nodo son casi lo mismo, uno es un puntero y el otro la estructura. Si sigues el código verás que con esos alias el código es más fácil de seguir.

Para ver como quedaría de la otra forma haz una copia del código y sustituye lista por struct nodo_t* y nodo por struct nodo_t y verás la diferencia.
#1286
Está un poco modificado pues defino un puntero directamente, pero los argumentos de push y pop esperan un puntero a puntero.

Como pusiste un ejemplo con push supuse que era una pila, así que el ejemplo implementa una pila.


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

typedef struct nodo_t {
    int valor;
    struct nodo_t* siguiente;
} nodo, *pila;

pila nueva_pila() {
    return NULL;
}

void push(pila *l, int n) {
    nodo *nuevo = malloc(sizeof(nodo));
    nuevo->valor = n;
    nuevo->siguiente = *l;
    *l = nuevo;
}

int pop(pila *l, int *dato) {
    int exito = 0;
    *dato = 0;
    nodo* a_borrar;
    if(*l) {
        *dato = (*l)->valor;
        a_borrar = *l;
        *l = (*l)->siguiente;
        free(a_borrar);
        exito = 1;
    }
    return exito;
}
   
int main() {
    pila mi_pila;
    int valor;
    int exito;
   
    mi_pila = nueva_pila();
    push(&mi_pila, 3);
    push(&mi_pila, 5);
    exito = pop(&mi_pila, &valor);
    if(exito) printf("%i\n", valor);
    exito = pop(&mi_pila, &valor);
    if(exito) printf("%i\n", valor);
    exito = pop(&mi_pila, &valor);
    if(exito) printf("%i\n", valor);
   
    return 0;
}
#1287
Un programa en C siempre debe devolver un valor entero comprendido entre 0 y 255 cuando termina.

Tu programa termina cuando termina main pero no retorna nada, de forma controlada. Para solventar esto pon como última instrucción en main return 0; así retornarás el valor 0, que según el estándar quiere decir que el programa ha finalizado sin problemas.
#1288
Programación C/C++ / Re: Ayuda con if-else
14 Abril 2016, 00:52 AM
Después de usar scanf para coger caracteres o números usa la instrucción
while(getchar()!='\n');
Esto vaciará el buffer stdin de todos los caracteres sobrantes.
#1289
Respuesta rápida:
Los parámetros de una función son una copia local del argumento de llamada.
Respuesta algo menos rápida:
Debes pasar un puntero a lista como argumento de la función.
Te doy media solución:
void push(lista **head, int value);

A partir de aquí me detengo y te invito a pensar porqué debe ser así.
#1290
¿Cómo vas con eso?

Nunca he montado uno de esos pero con la información de wikipedia en inglés hay una buena base para empezar.
https://en.wikipedia.org/wiki/Binary_expression_tree