elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Únete al Grupo Steam elhacker.NET


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Ayuda con estos códigos (Actualizado 22/06/2012)
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] 2 Ir Abajo Respuesta Imprimir
Autor Tema: Ayuda con estos códigos (Actualizado 22/06/2012)  (Leído 9,190 veces)
LoLo2207

Desconectado Desconectado

Mensajes: 9


Ver Perfil
Ayuda con estos códigos (Actualizado 22/06/2012)
« en: 26 Marzo 2012, 20:26 pm »

Hola, estoy intentando hacer un ejercicio sobre aritmética racional (sumar, restar, multiplicar y dividir fracciones). Al mostrar los resultados hay que simplificarlos, pero según veo en el depurador, no se pasan correctamente los valores a simplificar a la función. Qué debo cambiar? Seguramente sea muy obvio, pero soy malísimo con punteros y estructuras xD

Gracias.

Código
  1. /* Fuente: RACIONAL.C
  2.    Programa: ARITMETICA BASICA CON NUMEROS RACIONALES
  3.    Descripción: Este programa permite operar con números racionales. Un número racional
  4.    se caracteriza por estar expresado con un denominador y un denominador.
  5.    Las operaciones que contempla son:
  6.      - suma
  7.      - resta
  8.      - producto
  9.      - división
  10.    Además utiliza una función para proporcionar siempre la expresión irreducible del número
  11.    racional
  12. */
  13.  
  14. #include <stdio.h>
  15. #include <math.h>
  16. #include <ctype.h>
  17.  
  18. /* ---------------------------------------------------------- */
  19. /* Definiciones globales                                      */
  20. /* ---------------------------------------------------------- */
  21. typedef struct {
  22.   int num;   /* Numerador   */
  23.   int denom; /* Denominador */
  24. } Racional;
  25.  
  26. /* ---------------------------------------------------------- */
  27. /* Prototipos                                                 */
  28. /* ---------------------------------------------------------- */
  29.   void Modulo_Principal (void);
  30.   void Presentacion (void);
  31.   void LeerRacional (Racional *);
  32.   void MostrarRacional (Racional);
  33.   void SumaRacional (Racional, Racional, Racional *);
  34.   void RestaRacional (Racional, Racional, Racional *);
  35.   void MultiplicaRacional (Racional, Racional, Racional *);
  36.   void DivideRacional (Racional, Racional, Racional *);
  37.   void SimplificaRacional (Racional *);
  38.   int mcd (int, int);
  39.  
  40. /* ---------------------------------------------------------- */
  41.   int main (void) {
  42. /* ---------------------------------------------------------- */
  43.     char respuesta;
  44.  
  45.     system ("cls");
  46.     Presentacion();
  47.     do
  48.       { printf("\n");
  49.         Modulo_Principal();
  50.     printf("\n");
  51.     do
  52.       { printf("¿Otra ejecución (S/N)?: ");
  53.         fflush(stdin); /* Limpia el buffer de teclado */
  54.         respuesta = toupper(getchar());
  55.       }
  56.     while (respuesta != 'S' && respuesta != 'N');
  57.  
  58.       }
  59.     while (respuesta != 'N');
  60.  
  61.     printf("\n");
  62.     return 0;
  63.  
  64. } /* Fin del main */
  65.  
  66.  
  67. /* ---------------------------------------------------------- */
  68.   void Modulo_Principal (void) {
  69. /* ---------------------------------------------------------- */
  70.     Racional rac1, rac2, rsum, rres, rprod, rdiv;
  71.  
  72.     printf("Introduzca el primer número racional:\n");
  73.     LeerRacional(&rac1);
  74.     printf("Introduzca el segundo número racional:\n");
  75.     LeerRacional(&rac2);
  76.  
  77.     printf("\n");
  78.     SumaRacional (rac1, rac2, &rsum);
  79.     printf("Suma.......: ");
  80.     MostrarRacional(rsum);
  81.     printf("\n");
  82.  
  83.     RestaRacional (rac1, rac2, &rres);
  84.     printf("Resta......: ");
  85.     MostrarRacional(rres);
  86.     printf("\n");
  87.  
  88.     MultiplicaRacional (rac1, rac2, &rprod);
  89.     printf("Producto...: ");
  90.     MostrarRacional(rprod);
  91.     printf("\n");
  92.  
  93.     DivideRacional (rac1, rac2, &rdiv);
  94.     printf("División...: ");
  95.     MostrarRacional(rdiv);
  96.     printf("\n");
  97. }
  98.  
  99. /* ---------------------------------------------------------- */
  100.   void Presentacion (void) {
  101. /* ---------------------------------------------------------- */
  102.     puts("ARITMETICA BASICA CON NUMEROS RACIONALES");
  103.     puts("========================================");
  104.     puts("");
  105.     puts("Realiza la suma de números racionales");
  106.     puts("Siempre presenta la expresión irreducible del número racional");
  107.     puts("");
  108. }
  109.  
  110. /* ---------------------------------------------------------- */
  111.   void LeerRacional (Racional *r) {
  112. /* ---------------------------------------------------------- */
  113.       scanf("%d/%d", &(r->num), &(r->denom));
  114. }
  115.  
  116. /* ---------------------------------------------------------- */
  117.   void SumaRacional (Racional a, Racional b, Racional *r) {
  118. /* ---------------------------------------------------------- */
  119.  
  120.       if(a.denom == b.denom){
  121.        (r->num)=(a.num + b.num);
  122.        (r->denom)=(a.denom);
  123.       }else{
  124.        (r->denom)=(a.denom * b.denom);
  125.        (r->num)=(((r->denom/a.denom)*a.num) + ((r->denom/b.denom)*b.num));
  126.       }
  127.  
  128.       SimplificaRacional(&r);
  129. }
  130.  
  131.  
  132. /* ---------------------------------------------------------- */
  133.   void RestaRacional (Racional a, Racional b, Racional *r) {
  134. /* ---------------------------------------------------------- */
  135.  
  136.       if(a.denom == b.denom){
  137.        (r->denom)=(a.denom);
  138.        (r->num) = (a.num - b.num);
  139.       }else{
  140.        (r->denom)=(a.denom * b.denom);
  141.        (r->num)=(((r->denom/a.denom)*a.num) - ((r->denom/b.denom)*b.num));
  142.       }
  143.  
  144.    SimplificaRacional(&r);
  145. }
  146.  
  147.  
  148.  
  149. /* ---------------------------------------------------------- */
  150.   void MultiplicaRacional (Racional a, Racional b, Racional *r) {
  151. /* ---------------------------------------------------------- */
  152.  
  153.       (r->num)=(a.num*b.num);
  154.       (r->denom)=(a.denom*b.denom);
  155.       SimplificaRacional(&r);
  156. }
  157.  
  158.  
  159. /* ---------------------------------------------------------- */
  160.   void DivideRacional (Racional a, Racional b, Racional *r) {
  161. /* ---------------------------------------------------------- */
  162.  
  163.       (r->num)=(a.num*b.denom);
  164.       (r->denom=a.denom*b.num);
  165.       SimplificaRacional(&r);
  166. }
  167.  
  168.  
  169. /* ---------------------------------------------------------- */
  170.   void MostrarRacional (Racional r) {
  171. /* ---------------------------------------------------------- */
  172.     printf("%3d", r.num);
  173.     if (r.denom != 1)
  174.       printf(" /%3d", r.denom);
  175. }
  176.  
  177.  
  178. /* ---------------------------------------------------------- */
  179.   void SimplificaRacional (Racional *r) {
  180. /* ---------------------------------------------------------- */
  181. // Calcula el mcd del numerador y del denominador
  182. // Divide numerador y denominador por su mcd
  183. // Si la fraccion debe llevar segno negativo (num*dem <0)
  184. //    entonces el signo se coloca al numerador
  185.    int min;
  186.  
  187.       min=mcd(r->num, r->denom);
  188.       r->num = (r->num)/min;
  189.       r->denom =(r->denom)/min;
  190.       if((r->num * r->denom)<0){
  191.        r->num = - r->num;
  192.       }
  193. }
  194.  
  195.  
  196.  
  197. /* ---------------------------------------------------------- */
  198.   int mcd (int n, int d) {
  199. /* ---------------------------------------------------------- */
  200. /* Calcula el máximo común dividor de n y d */
  201. /* Precisa que d sea distinto de cero       */
  202. /* Precisa que n > d                        */
  203.    int c;
  204.  
  205.       if(n!=0 && d!=0 && n>d){
  206.        do{
  207.            c=n%d;
  208.            if(c!=0){
  209.                n=d;
  210.                d=c;
  211.            }
  212.        }while(c!=0);
  213.       }else{
  214.        return;
  215.       }
  216.  
  217. return d;
  218. }

EDIT: Para evitar abrir más hilos, pongo en este todas mis dudas personales. Nuevo programa añadido el 22/06/2012.


« Última modificación: 22 Junio 2012, 02:43 am por LoLo2207 » En línea

durasno


Desconectado Desconectado

Mensajes: 373


Ver Perfil
Re: Ayuda con una función de este código
« Respuesta #1 en: 26 Marzo 2012, 22:02 pm »

Hola LoLo2207! el problema es cuando llamas a la funcion SimplificaRacional. Vos le pasas la direccion del puntero r, (&r), lo que estas haciendo aca es pasarle a la funcion un puntero a puntero.
Solamente deberias pasarle el puntero, osea SimplificaRacional(r);

Saludos

PD: el programa tambien funcionaria con puntero a puntero solo que tendrias que saber como se utiliza


En línea

Ahorrate una pregunta, lee el man
LoLo2207

Desconectado Desconectado

Mensajes: 9


Ver Perfil
Re: Ayuda con una función de este código
« Respuesta #2 en: 27 Marzo 2012, 08:02 am »

Gracias, ya funciona perfectamente :D

A ver si he entendido bien, al llamar a la función, como en el prototipo ya sabe que recibirá un puntero, sólo tengo que poner el nombre del puntero, no la dirección, porque si no sería la direccion de un puntero, que a su vez sería la dirección de una direccíon, no?

Y lo de usar dobles punteros pues como que no, que además los prototipos me los da el profesor y nosotros sólo tenermos que rellenar el "esqueleto".
En línea

durasno


Desconectado Desconectado

Mensajes: 373


Ver Perfil
Re: Ayuda con una función de este código
« Respuesta #3 en: 27 Marzo 2012, 19:52 pm »

A ver si he entendido bien, al llamar a la función, como en el prototipo ya sabe que recibirá un puntero, sólo tengo que poner el nombre del puntero, no la dirección, porque si no sería la direccion de un puntero, que a su vez sería la dirección de una direccíon, no?  SI, es como vos decis :)

Saludos
En línea

Ahorrate una pregunta, lee el man
LoLo2207

Desconectado Desconectado

Mensajes: 9


Ver Perfil
Re: Ayuda con estos códigos (Actualizado 13/04/2012)
« Respuesta #4 en: 13 Abril 2012, 16:42 pm »

Nuevo programa: se supone que tiene que leer una ficha de un alumno creada mediante estructuras, y luego imprimirla. No me acaba de salir :( Qué lío de punteros, estructuras, typedef y la madre que lo trajo...

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. #define MAXN 10 /* Número máximo de notas del alumno */
  5.  
  6. typedef struct{
  7.    int dia;
  8.    int mes;
  9.    int anno;
  10. }tipo_fecha;
  11.  
  12. typedef struct{
  13.    char nombre[51];
  14.    int curso;
  15.    tipo_fecha fechaNacimiento;
  16.    char direccion[61];
  17.    float notas[MAXN];
  18. }tipo_alumno;
  19.  
  20. /* PROTOTIPOS */
  21.  
  22. void leerAlumno(tipo_alumno *);
  23. void imprimiralumno(tipo_alumno *);
  24.  
  25. /* FUNCIONES */
  26.  
  27. void leerAlumno(tipo_alumno * pa){
  28.    int i;
  29.  
  30.    printf("Introduzca el nombre y apellidos del alumno (max. 50 caracteres): ");
  31.    gets(pa->nombre);
  32.    printf("Curso: ");
  33.    scanf("%d", &pa->curso);
  34.    printf("Fecha de Nacimiento (dd/mm/aaaa): ");
  35.    scanf("%2d/%2d/%4d", &pa->fechaNacimiento.dia, &pa->fechaNacimiento.mes, &pa->fechaNacimiento.anno);
  36.    puts("Direccion: ");
  37.    fflush(stdin);
  38.    gets(pa->direccion);
  39.    for(i=0; i<MAXN; i++){
  40.        printf("Nota[%d]: ", i+1);
  41.        scanf("%f", &pa->notas[i]);
  42.    }
  43. }
  44.  
  45. void imprimirAlumno(tipo_alumno * pa){
  46.    int i;
  47.  
  48.    fflush(stdin);
  49.    printf("Nombre: %s", pa->nombre);
  50.    fflush(stdin);
  51.    printf("Curso: %d", pa->curso);
  52.    fflush(stdin);
  53.    printf("Fecha de Nacimiento: %2d/%2d/%4d\n", pa->fechaNacimiento.dia, pa->fechaNacimiento.mes, pa->fechaNacimiento.anno),
  54.    fflush(stdin);
  55.    printf("Direccion: %s\n", pa->direccion);
  56.    for(i=0; i<MAXN; i++){
  57.        printf("Nota[%d]: %2.1f\n", i+1, pa->notas[i]);
  58.    }
  59. }
  60.  
  61. int main (void){
  62.  
  63.    tipo_alumno alumno;
  64.    tipo_alumno * ptalumno;
  65.    ptalumno=&alumno;
  66.  
  67.    leerAlumno(ptalumno);
  68.  
  69.    imprimirAlumno(ptalumno);
  70.  
  71.  
  72. printf("\n\n");
  73. system("pause");
  74. return 0;
  75. }
  76.  

Por cierto, a ver si me aclaro con las estructuras. En mi libro vienen varias formas de declarar tipos y crear variables mediante el typedef
Código
  1. typedef struct tipo_alumno{
  2.    tipo1 miembro1;
  3.    tipo2 miembro2;
  4.    ...
  5.    tipoN miembroN;
  6. } var1, var2,...;
  7.  

El tipo_alumno es opcional si no quieres ponerle una etiqueta al tipo no? Pero si no se la pones no puedes crear por ejemplo una var3 después, o sí porque está puesto el typedef? Qué forma me recomendáis para definir un tipo de dato fuera del main?   :huh:
« Última modificación: 13 Abril 2012, 16:54 pm por LoLo2207 » En línea

durasno


Desconectado Desconectado

Mensajes: 373


Ver Perfil
Re: Ayuda con estos códigos (Actualizado 13/04/2012)
« Respuesta #5 en: 13 Abril 2012, 20:58 pm »

Hola! el programa te anda?? porque a mi me funciona bien...

Código
  1. typedef struct tipo_alumno{ //En este caso tipo_alumno es opcional
  2.    tipo1 miembro1;
  3.    tipo2 miembro2;
  4.    ...
  5.    tipoN miembroN;
  6. } var1, var2,...;
Lo que estas haciendo aca es declarar tipos de datos no variables; var1 y var2 no son variables, esto es por el typedef. Para crear una variable vas a tener que declarar, ej:
Código
  1. var1 MI_ESTRUCTURA; // MI_ESTRUCTURA es la variable

No es lo mismo hacer lo anterior q hacer:
Código
  1. struct tipo_alumno{ // En este caso tipo_alumno tambien es opcional
  2.    tipo1 miembro1;
  3.    tipo2 miembro2;
  4.    ...
  5.    tipoN miembroN;
  6. } var1, var2,...;
Aca si var1 y var2 son variables declaradas de forma global

Otra forma es no declarando variable globales:
Código
  1. struct tipo_alumno{ // [b]En este caso tipo_alumno  tiene que ir si o si[/b]
  2.    tipo1 miembro1;
  3.    tipo2 miembro2;
  4.    ...
  5.    tipoN miembroN;
  6. };
Para declarar una variable en este caso seria:
Código
  1. main()
  2. {
  3.  struct tipo_alumno MI_ESTRUCTURA; // esta variable es local al main
  4.   ......
  5. }


Ahora cual es la forma mas conveniente depende de cada uno, en mi caso no trabajo con variables globales y tampoco uso el typedef. Es por eso q prefiero el tercer ejemplo, me parece mas facil de entender

Espero te sirva, Saludos
En línea

Ahorrate una pregunta, lee el man
LoLo2207

Desconectado Desconectado

Mensajes: 9


Ver Perfil
Re: Ayuda con estos códigos (Actualizado 13/04/2012)
« Respuesta #6 en: 13 Abril 2012, 23:12 pm »

Gracias por responder. He estado haciendo mientras tanto otros ejercicios, y para todos ellos he utilizado lo siguiente (siempre tras los #include y los #define, y fuera del main o de cualquier otra función):

Código
  1. typedef struct tipo_jugador{
  2.    tipo1 miembro1;
  3.    tipo2 miembro2;
  4.    ...
  5.    tipoN miembroN;
  6. }tipo_jugador;
  7.  

Y luego en el main:
Código
  1. tipo_jugador equipo[MAX_JUG];

Y me funciona bien. Lo que quiero saber es si es muy redundante o no, y qué diferencia hay enter los dos tipo_jugador, el de antes y después de las llaves.

De todas formas, me he dado cuenta de que una función puede devolver una estructura por valor, ya que creía que como esa un tipo de dato compuesto pues se tenía que hacer sí o sí por referencia. Probaré a empezar de 0 con el programa anterior, ya que aunque me compilaba, no se guardaban bien los valores en las variables (y obviamente se imprimían cosas aleatorias).
En línea

durasno


Desconectado Desconectado

Mensajes: 373


Ver Perfil
Re: Ayuda con estos códigos (Actualizado 13/04/2012)
« Respuesta #7 en: 14 Abril 2012, 00:56 am »

Practicamente no hay ninguna diferencia, el tipo_jugador antes de la llave es el nombre de la estructura y el tipo_jugador despues de la llave es el nuevo tipo de dato definido por vos, en este caso lleva el mismo nombre

Saludos
En línea

Ahorrate una pregunta, lee el man
LoLo2207

Desconectado Desconectado

Mensajes: 9


Ver Perfil
Re: Ayuda con estos códigos (Actualizado 13/04/2012)
« Respuesta #8 en: 22 Junio 2012, 02:43 am »

Otra dudilla. Esta vez estoy con listas simplemente enlazadas.

Tengo que hacer un programa que cree una lista enlazada, que en su interior tenga un num. aleatorio >0 y que la muestre, junto con el nº de nodos. (hasta aquí todo bien)

El problema es que también tengo que pedir un nº por teclado y eliminar todos los nodos que contengan un nº igual o mayor al introducido, y me falla esta última función.

Os pongo sólo la función para ahorrar espacio. Si fuera necesario, luego pondría el programa completo.

Código
  1. void EliminarNodos(NODO *lst, int maximo){
  2.    NODO *indice=NULL, *anterior=NULL;
  3.  
  4.    if(lst!=NULL){
  5.        indice=lst;
  6.  
  7.  
  8.        while((indice->sig)!=NULL){
  9.            if((indice->num)>=maximo){
  10.                if(anterior==NULL){
  11.                    lst=(indice->sig);
  12.                    free(indice);
  13.                    indice=lst;
  14.                }else{
  15.                    (anterior->sig)=(indice->sig);
  16.                    free(indice);
  17.                    indice=anterior->sig;
  18.                }
  19.            }
  20.        }
  21.    }
  22. }

A ver si véis en qué me falla. Porque también tengo que hacer otro prog. muy parecido al anterior, pero en vez de eliminar nodos con el nº mayor, tengo que ordenar la lista y quitar los repetidos. Pero eso ya para luego, que si me sale este a lo mejor entendiendo lo que tenía mal puede que me salga el otro.

Saludos y gracias.
En línea

durasno


Desconectado Desconectado

Mensajes: 373


Ver Perfil
Re: Ayuda con estos códigos (Actualizado 22/06/2012)
« Respuesta #9 en: 22 Junio 2012, 08:24 am »

Hola! lo que subiste no funciona xq anterior siempre es igual a NULL, nunca entra al else; pero no esta del todo mal...

De todas formas el error principal esta en que no tenes claro el concepto de pasaje por valor y por pseudoreferencia. A la funcion vos le pasas el puntero lst, es decir en la llamada haces
Código
  1. EliminarNodos(lst, maximo); // pasas por valor a lst
El problema es que si vos tratas asi a lst cualquier modificacion que hagas en la funcion(es decir haces q apunte a otro lado) cuando retornes al main no va a tener efecto... Para resolver esto tenes q pasar a lst por pseudoreferencia
Código
  1. // en la llamada
  2. EliminarNodos(&lst, maximo); // paso la direccion de lst
y en la funcion:
Código
  1. void EliminarNodos(NODO **lst, int  maximo) // se trata como un puntero a puntero
  2. { }


Entonces, el codigo seria mas o menos asi:
Código
  1. void EliminarNodos(NODO **lst, int maximo){
  2.    NODO *indice=NULL, *anterior=NULL;
  3.   int flag;
  4.    if(*lst!=NULL){
  5.        indice=*lst;
  6.  
  7.        while((indice)!=NULL){
  8.             flag=0;
  9.            if((indice->num)>=maximo){
  10.                if(indice==*lst){ // es decir es el inicio de la lista
  11.                    *lst=indice->sig; // ahora el inicio de la lista es el siguiente
  12.                      free(indice);
  13.                      indice=*lst;
  14.                }else{ // no es el inicio
  15.                    anterior->sig=indice->sig;
  16.                    free(indice);
  17.                    indice=anterior->sig;
  18.                }
  19.              flag=1;
  20.            }
  21.            if(!flag) { /* nose borran nodo */
  22.               anterior=indice;
  23.               indice=anterior->sig; /* cambia al sig nodo */
  24.             }
  25.        } /* fin del while */
  26.    }
  27. }
Fijate q solo agregue un par de cosas a lo q tenias(ya q no estaba tan mal). Te falto considerar que pasa cuando indice->num>=maximo es falso, el bucle se vuelve infinito ya que no cambias de nodo, te falto agregar indice=anterior->sig; pero para q esto funcione bien agregue un flag. Cuando flag=0 es porque no se cumplio que num>=maximo(nose borran nodos) entonces se ejecuta
Código
  1.            if(!flag) {
  2.               anterior=indice;
  3.               indice=anterior->sig; /* cambia al sig nodo */
  4.             }
de lo contrario flag=1 nose ejecuta lo anterior mencionada...

Si funciona lo que puse, analiza porque lo hice asi teniendo en cuenta todas las consideraciones. Saludos
« Última modificación: 22 Junio 2012, 08:27 am por durasno » En línea

Ahorrate una pregunta, lee el man
Páginas: [1] 2 Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
[Aporte] Factorización Relativamente Rápida - Actualizado 18/08/2012 -
.NET (C#, VB.NET, ASP)
Keyen Night 0 4,962 Último mensaje 15 Marzo 2011, 04:38 am
por Keyen Night
Como se desencriptan códigos como estos: ''sºÁÓrX''
Programación General
Ngeooz 0 1,823 Último mensaje 29 Diciembre 2013, 23:58 pm
por Ngeooz
¿Cómo mejorar estos códigos?
PHP
Richter{}; 1 1,670 Último mensaje 16 Noviembre 2014, 00:09 am
por dimitrix
Alguien me explicaría que son estos codigos
Programación C/C++
naidmen 2 2,054 Último mensaje 13 Febrero 2017, 21:17 pm
por dato000
(AYUDA POR FAVOR) determinar salida en estos códigos
Programación C/C++
victorportes 1 1,661 Último mensaje 10 Octubre 2018, 01:25 am
por Beginner Web
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines