Problema en c/c++ PERDON

Started by Danielo515, February 05, 2009, 08:32:16 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Danielo515

Perdonad que publique aquí mi problema, pero es una de las comunidades de programación en las que más confío y que más seguridad me da, además de que contestan muy bien.

Tengo este programa, el problema está en la funcion que devuelve el cambio. A veces dice, por ejemplo, si elijes 1 (0.70) e introduces una moneda de 2 euros, te dice que el cambio es de 1.30, pero te de vuelve 1$ una de 0.20 y una de 0.5. Este problema me lo da en el ordenador del salon (compilado con dev). Si lo pruebo en otro compilador dev también, pero con extensión .c (en el del salon, el conio2.h si lo compilo como c me da error) el error solo me lo da si elijo el 3 (0.45) y pagando con monedas de 0.05 me devuelve mal, y acepta monedas de mas.

LOS CONTROLES:
0-5 Elegir bebida
1-6 INTRODUCIR MONEDA 1$ 2$ 0.5$ 0.2$ 0.1$ 0.05$ (una vez elegida la bebida)

Probad esas dos combinaciones, pedid un 3 y pagad con monedas de 0.05 y pedid un 1 y pagad con una moneda de 2$

[code language="c"]#include <stdio.h>
#include <stdlib.h>
#include <conio2.h>

#define eleccion 30,4

#define rojo textcolor(12);
#define azul 9
#define blanco textcolor(15);
#define verde textcolor(10);
#define amarillo textcolor(14);


//FONDOS
#define fgris textbackground(7);
#define fmarron textbackground(6);
#define fazul 1

char name[][13]={"Cola","Refresco","Cerveza","Agua","Agua","Cocolatina"};
float precio[]={.75,.70,.60,.45,.90,.80};
int dos=50,uno=60,cincuenta=100,veinte=80,diez=60,cinco=100;

void pared(){
for(int x=0;x<30;x++){
        for(int j=0;j<20;j++){
             for(int i=1;i<4;i++){
                  fmarron;
                  printf(" ");
                               }//for i
                  fgris;
                  printf(" ");
                  fmarron;
                  printf(" ");                  printf(" ");                  printf(" ");
             
             }//for j
             printf(" ");
        }//for x       
     }// pared
     
float menu(){
      char seleccion;
      int sel;
      do{
            seleccion=getch();
            sel=atoi(&seleccion);
      }while(sel>5 || sel<0);
      textcolor(azul);
      gotoxy(eleccion);
      printf("Ha elegido %s",name[sel]);
      return precio[sel];
      }

float aceptar_monedas(float precio){
      int in; //el valor numerico de la moneda introducida
      char introducido; //la moneda que se introduce
      float metido=0.0; //la cantidad que se ha metido hasta ahora

    //---------- LO QUE FALTA POR INTRODUCIR ----------------//
      gotoxy(30,8);
      printf("Queda por introducir:");
     
      gotoxy(58,8); verde; printf("Introducido: ");
                  gotoxy(52,8);
                  rojo;
                  printf("%.2f",precio);   
                  gotoxy(70,8);
                  printf("%.2f",metido);                                                                         
      while(precio>0.0){
                   
                      introducido=getch();
                      in=atoi(&introducido);
                     
         //-------Linea que borra el mensaje de moneda no valida---------//
                      gotoxy(30,6); // en caso de que existiera el mensaje de moneda no valida
                      printf("                                   ");  //lo borramos nada más capturar la moneda siguiente
         //-------Lo hacemos nada más capturar la moneda siguiente -----//
         
                     
                      switch(in){
                                 case 1:
                                 uno++;
                                 precio-=1.0;
                                 metido+=1.0;
                                 break;
                                 
                                 case 2:
                                 dos++;
                                 precio-=2.0;
                                 metido+=2.0;
                                 break;
                                 
                                 case 3:
                                 cincuenta++;
                                 precio-=0.5;
                                 metido+=0.5;
                                 break;
                                 
                                 case 4:
                                 veinte++;
                                 precio-=0.2;
                                 metido+=0.2;                                 
                                 break;
                                 
                                 case 5:
                                 diez++;
                                 precio-=0.1;
                                 metido+=0.1;                                 
                                 break;
                                 
                                 case 6:
                                 cinco++;
                                 precio-=0.05;
                                 metido+=0.05;                                 
                                 break;
                                 
                                 default:
                                 rojo;
                                 gotoxy(30,6);
                                 printf("Debe introducir una moneda valida!!");  //Línea a modificar para hacerlo estético
                                 
                                 }
                  gotoxy(52,8);
                  rojo;
                  printf("%.2f",precio);   
                  gotoxy(70,8);
                  printf("%.2f",metido);
                      }//while
      return(-precio); //devuelve lo que ha introducido de más, es decir, cúanto se ha pasado del precio introducido
}//aceptar monedas

float dar_cambio(float cantidad){
int ent;

gotoxy(30,10);

if(cantidad>=1.0){
                  ent=(int)cantidad/1;

                 if(ent>=uno){
                              cantidad-=uno;
                              blanco; printf("  %d X ",uno);
                              amarillo; printf("1$ ");
                 }else{
                       uno-=ent;
                       cantidad-=ent;
                       blanco; printf("  %d X ",ent);
                       amarillo; printf("1$ ");
                   }//else
                   }//if
                   
if(cantidad>=0.5){
                  ent=(int)(cantidad/0.5);
                 
                  if(ent>=cincuenta){
                   cantidad-=(cincuenta*0.5);
                   blanco; printf("  %d X ",cincuenta);
                   amarillo; printf("0.50$ ");
                   }else{
                         cincuenta-=ent;
                         cantidad-=(ent*0.5);
                   blanco; printf("  %d X ",ent);
                   amarillo; printf("0.50$ ");
                   }
                   }
                   
                   
if(cantidad>=0.2){
                  ent=(int)(cantidad/0.2);
                 
                  if(ent>=veinte){
                   cantidad-=(veinte*0.2);
                   blanco; printf("  %d X ",veinte);
                   amarillo; printf("0.20$ ");
                   }else{
                         veinte-=ent;
                         cantidad-=(ent*0.2);
                   blanco; printf("  %d X ",ent);
                   amarillo; printf("0.20$ ");
                   }
                   }
                   
                   
if(cantidad>=0.108){
                  ent=(int)(cantidad/0.1);
                 
                  if(ent>=diez){
                   cantidad-=(diez*0.1);
                   blanco; printf("  %d X ",diez);
                   amarillo; printf("0.10$ ");
                   }else{
                         diez-=ent;
                         cantidad-=(ent*0.1);
                   blanco; printf("  %d X ",ent);
                   amarillo; printf("0.10$ ");
                   }//else
                   }//if

if(cantidad>=0.05){
                  ent=(int)(cantidad/0.05);
                 
                  if(ent>=cinco){
                   cantidad-=(cinco*0.05);
                   blanco; printf("  %d X ",cinco);
                   amarillo; printf("0.05$ ");
                   }else{
                         cinco-=ent;
                         cantidad-=(ent*0.05);
                   blanco; printf("  %d X ",ent);
                   amarillo; printf("0.05$ ");
                   }//else
                   }//if
    }    //dar cambio


int main( )
{
float precio,cambio;
//pared();
precio=menu();
gotoxy(30,5);
verde;
printf("PRECIO: %.2f\n",precio);
cambio=aceptar_monedas(precio); //funcion que acepta monedas y escribe la cantidad restante

    //--- Borrar cantidad restante por introducir --- //
            gotoxy(52,8); // una vez llegados a este punto, ya no queda nada por introducir, y puesto que la funcion anterior..
            printf("0.00"); //..muere antes de refrescar la cantidad a introducir, lo hacemos manualmente :P

gotoxy(30,9);
printf("Su cambio es: %.2f",cambio);
dar_cambio(cambio);
  getch();
} [/code]

DCelso

conoces elrincondelc ¿no?
Si no recuerdo mal este problema o uno parecido se resolvió hace tiempo.
Voy a compilarlo a ver si veo algo así rápidamente, saludos.
Monstruos Diabólicos

"A PAck of classic GAMEs For BennuGD" en desarrollo
http://code.google.com/p/apagame4be/

DCelso

Lo tenía que haber visto antes sin hacer pruebas. Cachis, que lento soy.
Es el problema de siempre, nada de floats en C, dan problemas de redondeo, usa siempre doubles y fin del problema. resulta que un float 0.10 entre /0.5 da 1.999 que al truncar es 1, e ahí el problema.
Solución, redondear los floats(un poquito cutrecillo diría yo) o usar doubles.
He tenido que rehacer por completo tu forma de mostrar la información, la conio no es standar, no se de donde te pillaste la conio2, yo la he bajado de una página y no se ve un pirulo al ejecutar tu codigo. Te dejo aqui el mamotreto que he formado para poder jugar a tu mini juego de "vending" :D.

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

#define eleccion 30,4
#include <math.h>

char
name[][13] = { "Cola", "Refresco", "Cerveza", "Agua", "Agua",
"Cocolatina" };
float ar_precio[] = { .75, .70, .60, .45, .90, .80 };

int dos = 50, uno = 60, cincuenta = 100, veinte = 80, diez = 60, cinco = 100;

float monedas[8]={0.0,1.0,2.0,0.5,0.2,0.1,0.05};

float menu() {
char seleccion;
int sel;
do {
seleccion = getchar();
getchar();
sel = atoi(&seleccion);
} while (sel > 5 || sel < 0);
printf("Ha elegido %s\n", name[sel]);
return ar_precio[sel];
}

float aceptar_monedas(float precio) {
int in; //el valor numerico de la moneda introducida
char introducido; //la moneda que se introduce
float metido = 0.0; //la cantidad que se ha metido hasta ahora

printf("Queda por introducir: ");
printf("%.2f\n", precio);
printf("Introducido: ");
printf("%.2f\n", metido);
while (precio > 0.0) {
introducido = getchar();
getchar();
in = atoi(&introducido);

switch (in) {
case 1:
uno++;
precio -= 1.0;
metido += 1.0;
break;

case 2:
dos++;
precio -= 2.0;
metido += 2.0;
break;

case 3:
cincuenta++;
precio -= 0.5;
metido += 0.5;
break;

case 4:
veinte++;
precio -= 0.2;
metido += 0.2;
break;

case 5:
diez++;
precio -= 0.1;
metido += 0.1;
break;

case 6:
cinco++;
precio -= 0.05;
metido += 0.05;
break;

default:
printf("Debe introducir una moneda valida!!\n"); //Línea a modificar para hacerlo estético

}
printf("Queda por introducir: ");
printf("%.2f\n", precio);
printf("Introducido: ");
printf("%.2f\n", metido);
}//while
return (-precio); //devuelve lo que ha introducido de más, es decir, cúanto se ha pasado del precio introducido
}//aceptar monedas

void dar_cambio(float cantidad) {
int ent;

if (cantidad >= 1.0) {
ent = (int) cantidad / 1;

if (ent >= uno) {
cantidad -= uno;
printf("%d X 1$\n", uno);
} else {
uno -= ent;
cantidad -= ent;
printf("%d X 1$\n", ent);
}//else
}//if

if (cantidad >= 0.5) {
ent = (int) (cantidad / 0.5);

if (ent >= cincuenta) {
cantidad -= (cincuenta * 0.5);
printf("%d X 0.50$\n", cincuenta);
} else {
cincuenta -= ent;
cantidad -= (ent * 0.5);
printf("%d X 0.50$\n", ent);
}
}

if (cantidad >= 0.2) {
ent = (int) (cantidad / 0.2);

if (ent >= veinte) {
cantidad -= (veinte * 0.2);
printf("%d X 0.20$\n", veinte);
} else {
veinte -= ent;
cantidad -= (ent * 0.2);
printf("%d X 0.20$\n", ent);
}
}

if (cantidad >= 0.108) {
ent = (int) (cantidad / 0.1);

if (ent >= diez) {
cantidad -= (diez * 0.1);
printf("%d X 0.10$\n", diez);
} else {
diez -= ent;
cantidad -= (ent * 0.1);
printf("%d X 0.10$\n", ent);
}//else
}//if

if (cantidad >= 0.05) {
printf("cantidad: %f\n",cantidad);
printf("cantidad/0.05: %f\n",cantidad / 0.05);
ent = (int) (cantidad / 0.05) ;
printf("ent(truncado): %d\n",ent);
ent = (int) round(cantidad / 0.05) ;
printf("ent(redondeado): %d\n",ent);
if (ent >= cinco) {
cantidad -= (cinco * 0.05);
printf("%d X 0.05$\n", cinco);
} else {
cinco -= ent;
cantidad -= (ent * 0.05);
printf("%d X 0.05$\n", ent);
}//else
}//if
} //dar cambio


int main() {
float precio, cambio;
for (int i=0; i<5;i++)
printf("%d.-%s: %.2f$\n",i,name[i],ar_precio[i]);
precio = menu();
printf("\nMonedas\n");
for (int i=1; i<7;i++)
printf("%d.-%.2f\n",i,monedas[i]);
cambio = aceptar_monedas(precio); //funcion que acepta monedas y escribe la cantidad restante

printf("Su cambio es: %.2f\n", cambio);
dar_cambio(cambio);
getchar();
}

Monstruos Diabólicos

"A PAck of classic GAMEs For BennuGD" en desarrollo
http://code.google.com/p/apagame4be/

Danielo515

#3
Dcelso, muchas gracias por contestar, pero el mat.h, me redondea y me trunca igual, en los dos vale 1.

Si quieres te mando el conio, tal como lo he descargado. Voy a poner también aquí mi codigo para que lo compiles, con devC++ una vez instalada conio. Esta conio es autoejecutable, solo abrir y doble click.

Luego en opciones del linker pon -lconio.
Tutorial:
http://www.programacionenc.net/modules.php?name=Tutoriales&d_op=vertuto&lid=28

Danielo515

Prueba a pedir un dos y pagar con un dos. Verás que se te queda con 5 centimos, además de que te da en vez de dos monedas de .20 (para hacer 0.4) te da una de .20 una de .10 y una de .5 y eso antes no me pasaba.

Muchas muchas gracias por tu ayuda.

Un saludo.

SplinterGU

Ni float ni doubles... para importes, usa enteros multiplicados por 100 (2 digitos decimales) por ejemplo, si necesitas decir 1€ pone 100, 0.50€ es 50... trabaja asi que no vas a tener problemas... los numeros de coma flotante tienen problemas de precision...
tambien hay librerias especificas para manejar numeros con decimales sin errores, pero lo mas simple es usar enteros.
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

DCelso

Ostras, muy buena idea Splinter, no lo pensé así derepente, pero sí recuerdo haberlo empleado alguna que otra vez. :D
Monstruos Diabólicos

"A PAck of classic GAMEs For BennuGD" en desarrollo
http://code.google.com/p/apagame4be/

DCelso

killo, prueba tu código, también pasa lo mismo, es culpa de los floats, 0.40/0.20 no da 2, sino 1.999 y al truncar queda 1. Pasa también con doubles.

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

#define eleccion 30,4

char
name[][13] = { "Cola", "Refresco", "Cerveza", "Agua", "Agua",
"Cocolatina" };
double ar_precio[] = { .75, .70, .60, .45, .90, .80 };

int dos = 50, uno = 60, cincuenta = 100, veinte = 80, diez = 60, cinco = 100;

double monedas[8]={0.0,1.0,2.0,0.5,0.2,0.1,0.05};

double menu() {
char seleccion;
int sel;
do {
seleccion = getchar();
getchar();
sel = atoi(&seleccion);
} while (sel > 5 || sel < 0);
printf("Ha elegido %s\n", name[sel]);
return ar_precio[sel];
}

double aceptar_monedas(double precio) {
int in; //el valor numerico de la moneda introducida
char introducido; //la moneda que se introduce
double metido = 0.0; //la cantidad que se ha metido hasta ahora

printf("Queda por introducir: ");
printf("%.2f\n", precio);
printf("Introducido: ");
printf("%.2f\n", metido);
while (precio > 0.0) {
introducido = getchar();
getchar();
in = atoi(&introducido);

switch (in) {
case 1:
uno++;
precio -= 1.0;
metido += 1.0;
break;

case 2:
dos++;
precio -= 2.0;
metido += 2.0;
break;

case 3:
cincuenta++;
precio -= 0.5;
metido += 0.5;
break;

case 4:
veinte++;
precio -= 0.2;
metido += 0.2;
break;

case 5:
diez++;
precio -= 0.1;
metido += 0.1;
break;

case 6:
cinco++;
precio -= 0.05;
metido += 0.05;
break;

default:
printf("Debe introducir una moneda valida!!\n"); //Línea a modificar para hacerlo estético

}
printf("Queda por introducir: ");
printf("%.2f\n", precio);
printf("Introducido: ");
printf("%.2f\n", metido);
}//while
return (-precio); //devuelve lo que ha introducido de más, es decir, cúanto se ha pasado del precio introducido
}//aceptar monedas

void dar_cambio(double cantidad) {
int ent;

if (cantidad >= 1.0) {
ent = (int) cantidad / 1;

if (ent >= uno) {
cantidad -= uno;
printf("%d X 1$\n", uno);
} else {
uno -= ent;
cantidad -= ent;
printf("%d X 1$\n", ent);
}//else
}//if

if (cantidad >= 0.5) {
ent = (int) (cantidad / 0.5);

if (ent >= cincuenta) {
cantidad -= (cincuenta * 0.5);
printf("%d X 0.50$\n", cincuenta);
} else {
cincuenta -= ent;
cantidad -= (ent * 0.5);
printf("%d X 0.50$\n", ent);
}
}

if (cantidad >= 0.2) {
ent = (int) (cantidad / 0.2);
printf("cantidad:%f\n",cantidad);
printf("ent:%d\n",ent);

if (ent >= veinte) {
cantidad -= (veinte * 0.2);
printf("%d X 0.20$\n", veinte);
} else {
veinte -= ent;
cantidad -= (ent * 0.2);
printf("%d X 0.20$\n", ent);
}
}

if (cantidad >= 0.1) {
ent = (int) (cantidad / 0.1);

if (ent >= diez) {
cantidad -= (diez * 0.1);
printf("%d X 0.10$\n", diez);
} else {
diez -= ent;
cantidad -= (ent * 0.1);
printf("%d X 0.10$\n", ent);
}//else
}//if
if (cantidad >= 0.05) {
ent = (int) (cantidad / 0.05) ;
if (ent >= cinco) {
cantidad -= (cinco * 0.05);
printf("%d X 0.05$\n", cinco);
} else {
cinco -= ent;
cantidad -= (ent * 0.05);
printf("%d X 0.05$\n", ent);
}//else
}//if
} //dar cambio


int main() {
double precio, cambio;
for (int i=0; i<5;i++)
printf("%d.-%s: %.2f$\n",i,name[i],ar_precio[i]);
precio = menu();
printf("\nMonedas\n");
for (int i=1; i<7;i++)
printf("%d.-%.2f\n",i,monedas[i]);
cambio = aceptar_monedas(precio); //funcion que acepta monedas y escribe la cantidad restante

printf("Su cambio es: %.2f\n", cambio);
dar_cambio(cambio);
getchar();
}

En cuanto a usar conio, no se que narices pasa pero en cygwin/gcc no va lo que me pasas, se ve mal.
Ya me habeis picado y la he optimizado y pasado a enteros, me ha quedado este codiguillo.

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

char
name[][13] = { "Cola", "Refresco", "Cerveza", "Agua", "Agua",
"Cocolatina" };
int ar_precio[] = { 75, 70, 60, 45, 90, 80 };


int monedas[8]={0,100,200,50,20,10,5};

int menu() {
char seleccion;
int sel;
do {
seleccion = getchar();
getchar();
sel = atoi(&seleccion);
} while (sel > 5 || sel < 0);
printf("Ha elegido %s\n", name[sel]);
return ar_precio[sel];
}

int aceptar_monedas(int precio) {
int in; //el valor numerico de la moneda introducida
char introducido; //la moneda que se introduce
int metido = 0; //la cantidad que se ha metido hasta ahora

printf("Queda por introducir: ");
printf("%.2f\n", precio/100.0);
printf("Introducido: ");
printf("%.2f\n", metido/100.0);
while (precio > 0) {
introducido = getchar();
getchar();
in = atoi(&introducido);

if (in >0 && in<7){
precio -=monedas[in];
metido +=monedas[in];
}else
printf("Debe introducir una moneda valida!!\n"); //Línea a modificar para hacerlo estético

printf("Queda por introducir: ");
printf("%.2f\n", precio/100.0);
printf("Introducido: ");
printf("%.2f\n", metido/100.0);
}//while
return (-precio); //devuelve lo que ha introducido de más, es decir, cúanto se ha pasado del precio introducido
}//aceptar monedas

void dar_cambio(int cantidad) {
int ent;

for (int i=1;i<7;i++)
if (cantidad >= monedas[i]) {
ent = (int) cantidad / monedas[i];
cantidad -= ent*monedas[i];
printf("%d X %.2f$\n", ent,monedas[i]/100.0);
}

} //dar cambio


int main() {
int precio, cambio;
for (int i=0; i<5;i++)
printf("%d.-%s: %.2f$\n",i,name[i],ar_precio[i]/100.0);
precio = menu();
printf("\nMonedas\n");
for (int i=1; i<7;i++)
printf("%d.-%.2f\n",i,monedas[i]/100.0);
cambio = aceptar_monedas(precio); //funcion que acepta monedas y escribe la cantidad restante

printf("Su cambio es: %.2f\n", cambio/100.0);
dar_cambio(cambio);
getchar();
}

Monstruos Diabólicos

"A PAck of classic GAMEs For BennuGD" en desarrollo
http://code.google.com/p/apagame4be/

SplinterGU

cuidado tambien con la impresion del entero /100.0, yo diria hacerte una funcion que pase el entero a string y luego ahi entre los ultimos 2 digitos le colocas el punto decimal... no es algo muy bonito ni optimo, pero es preciso.
Resumiendo, si se trata de importe, no usar numeros de punto flotante para nada.
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

Danielo515

Splinter... ... Eres el mejor!! Y Dcelso También por supuesto!! Ya funciona perfecto!! No he podido postear antes porque me he ido a trabajar.

Este mismo post está en otros foros de c/c++ específicos y aún no me han contestado. Sabía que hacía bien poniendolo aquí. Muchas Muchas Gracias a todos.

Como bonus track, el programilla compilado para que podais verlo con colorines y pijadas.

SplinterGU

Download Lastest BennuGD Release: http://www.bennugd.org/node/2

SplinterGU

A todo esto, por que en C y no en Bennu? :)
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

DCelso

 ;).
Ya te digo, en bennu estaría curuioso, ya con imagenes y sonido :D.
A que lo hago :D.
Monstruos Diabólicos

"A PAck of classic GAMEs For BennuGD" en desarrollo
http://code.google.com/p/apagame4be/

SplinterGU

con bennu tambien se pueden hacer programas de consola... sin problemas... cierto es que no hay funciones para posicionar el cursor y colores de texto, pero si se puede usar consola sin graficos.
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

Danielo515

Que yo sepa si se pueden poner colores de texto no? y posicionar el cursor. ¿O te refieres a que bennu tiene un modo especial de consola? Si es así no tenía ni idea. Pero... el problema de bennu es la captura de datos desde teclado, que es un poco coñazo... ¿o se ha mejorado esto ultimamente?


Por cierto, tengo un problema con el buffer de entrada en mi programa, y es que no consigo limpiarlo!!! Uso la función getch y por lo visto, captura cosas un poco atiguas, tecleadas hace un rato.