Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: FranAI en 23 Abril 2020, 03:48 am



Título: Problema al usar while
Publicado por: FranAI en 23 Abril 2020, 03:48 am
Soy principiante en cuanto a c++ respecta, mi inconveniente es el siguiente: Al pedirle al usuario que ingrese por segunda vez un numero, si el usuario ingresa la letra "n" debe terminarse el ciclo y mostrar por pantalla la cantidad de números introducidos por el usuario, así como, la suma de los resultados calculados. Mi problema es la condicion del while. Como puedo comparar un int con un char? La variable que se almacena en el segundo ingreso es de tipo entero, no deberia cambiarla a char y comparar? Como lo hago? ¿while (num2 != letra1);?

Código:
#include <iostream>
#include <stdio.h>
using namespace std;
int num;
int num2;
int i = 0;
int i2 = 0;
int i3 = 0;
int result = 0;
int result2 = 0;
int finalresult = 0;
char letra1 = 'n';
int main()
{
    do
    {
        cout << "Ingrese un numero entero: " << endl;
        cin >> num;
        i = i + 1;
        result = num * num - num;
        cout << num <<  " * " << num << " - " <<num<<  " = " << result << endl;
        cout << "Desea ingresar otro numero? " << endl;
        cin >> num2;
        i2 = i2 + 1;
        result2 = num2 * num2 - num2;
        finalresult =  finalresult + result + result2;
    }while (num2 != letra1);
    i3 = i2 + i;
    cout << i3 << " numeros ha ingresado el usuario." << endl;
    cout << "Suma de resultados calculados: " << finalresult << endl;
    return 0;
}


Título: Re: Problema al usar while
Publicado por: engel lex en 23 Abril 2020, 05:16 am
probaste tu codigo? falla cuando introduces n?


por cierto mezclas librerias del standard C y C++, las librerias del standard no llevan.h, es decir, no es <stdio.h> sino <cstdio>


Título: Re: Problema al usar while
Publicado por: @XSStringManolo en 23 Abril 2020, 06:09 am
 Te recomendaría que lo hicieses de cero de nuevo hicieses otro tipo de programas que tengas más claros mentalmente. Calculadores, conversiones de horas a minutos...


Tienes algunas cosas a mejorar:


- Faltan saltos de línea y organización para hacer el código más legible. Opcionalmente deberías añadir comentarios de para que es cada cosa, nombres de variables más descriptivos... Si no organizas todo exhaustivamente pronto montarás un buen lío cuando hagas algún programa de más de 100 lineas de código.


- Tienes un montón de variables que sobran, puedes reusar una para varias cosas o incluir en el cout la operación cuando no vayas a reusar una variable más.


- Tienes varios errores de lógica. La comprobación del while se hace al final, por lo que cuando el usuario introduzca la n vas a intentar operar con la letra n en lugar de un número porque el programa continua ejecutándo el bloque de código del do hasta que se llega al while y se comprueba que se introduzco una letra. Lo mismo pasa con los contadores (variables i) que los aumentas a pesar de que se introduzcan 2 n. Hay una solución que a mi parecer es fea y poco recomendada pero podría comprobar con un if y un static cast si se metio la letra n y hacer un break; dentro del if para saltar fuera del cuerpo del while. Tendrías que alterar un poco la estructura del código y funcionaría. A mi personalmente no es una opción que me guste y en tu caso programaría cosas más sencillas o pasaría a otra cosa, porque esto va a ser romperte mucho la cabeza para poco provecho a nivel de aprendizaje.


- Solo necesitas un contador, no 3.


- Tienes trozos de código innecesarios y repetitivos.


- El do y el casteo por el que preguntas static_cast<int>('n'); son innecesarios en este programa.


- No tienes ningún tipo de pausa en el programa. Puede que tu IDE las integre en desarrollo pero en varios sistemas si ejecutas el binario compilado, este no tiene pausa y se cierra la consola sin poder ver el resultado. Para evitarlo añade siempre antes del return 0 de la función principal main cin.get(); Si no te funciona y no sabes el por qué, agrega también cin.ignore(); antes del cin.get(); Estos métodos vienen con el cin en la biblioteca iostream.


- Puedes usar i += 1 o usar ++i en lugar de i = i + 1; Todas las formas hacen casi lo mismo.


- No hace falta que llames 2 veces seguidas al cout, puedes saltar de línea tranquilamente.


- char letra no te hace falta, pero en caso que lo pongas deberías declaralo como const o usando un #define ya que se supone que la letra va a ser siempre la misma.








Título: Re: Problema al usar while
Publicado por: WHK en 23 Abril 2020, 11:00 am
Citar
- El do y el casteo por el que preguntas static_cast<int>('n'); son innecesarios en este programa.

Y como te aseguras que el usuario no ha introducido otra cosa que no sea un valor numérico? y como sumas el total de todas las operaciones del loop?

Citar
No tienes ningún tipo de pausa en el programa. Puede que tu IDE las integre en desarrollo pero en varios sistemas si ejecutas el binario compilado, este no tiene pausa y se cierra la consola sin poder ver el resultado.

No veo la necesidad de hacer una pausa, vamos, es una aplicación de terminal, no vienes desde windows y le haces doble click al ejecutable, se supone que lo estás llamando desde el interprete de comandos, a demás.

Citar
char letra no te hace falta

Y como finaliza la instrucción del input del while?

Lo que te hace falta FranAI es transformar tu input a integer siempre y cuando este sea un valor numérico, en caso contrario no podrás transformar "n" a entero y te dará un error de memoria y la validación de contenido de un valor entero de un std string lo debes hacer recorriendo cada caracter, yo transformé cada uno al valor decimal y comrpobé si era el valor de un dígito. También entendí que la suma de los loops es para sumar el resultado de cada operación dentro del loop, asi que lo modifiqué poniendo las variables dentro del mismo loop para evitar globalizar las variables y tener basura en la memoria cuando liberes el proceso, las variables temporales las puse dentro del mismo while para que se autodestruyan en cada iteración. A demás, las palabras no se consideran como operaciones matemáticas asi que el contador lo puse justo después de la validación. Mira, algo así:

Código:
#include <iostream>
#include <string>

int main()
{
    std::string input;
    int totals  = 0;
    int nInputs = 0;

    while(1)
    {
        std::cout << "Ingrese un numero entero (o 'n' para finalizar): "; // no flush
        std::cin >> input;
        
        if(input.compare("n") == 0)
        {
            break;
        }

        bool isNumeric = true;
        for(int i = 0; i <= (input.length() - 1); i++)
        {
            if(((int)input[i] < 48) || ((int)input[i] > 57)) // decimal
            {
                isNumeric = false;
                std::cout << "El valor no es numérico. Intentalo nuevamente." << std::endl;
                break;
            }
        }

        if(!isNumeric)
        {
            continue;
        }

        nInputs++;

        int num   = std::stoi(input);
        int total = num * num - num;
        totals += total;

        std::cout << num <<  " * " << num << " - " << num <<  " = " << total << std::endl;
    }

    std::cout << nInputs << " numeros ha ingresado el usuario." << std::endl;
    std::cout << "Suma de resultados calculados: " << totals << std::endl;

    return 0;
}

Para compilar y ejecutar:

Código:
whk@machine:~/Escritorio$ g++ test.cpp -o test
whk@machine:~/Escritorio$ file test
test: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, not stripped
whk@machine:~/Escritorio$ ./test
Ingrese un numero entero (o 'n' para finalizar): 1
1 * 1 - 1 = 0
Ingrese un numero entero (o 'n' para finalizar): 5
5 * 5 - 5 = 20
Ingrese un numero entero (o 'n' para finalizar): abc
El valor no es numérico. Intentalo nuevamente.
Ingrese un numero entero (o 'n' para finalizar): 500
500 * 500 - 500 = 249500
Ingrese un numero entero (o 'n' para finalizar): n
4 numeros ha ingresado el usuario.
Suma de resultados calculados: 249520

También podrías simplificar "n*n-n" como "n*(n-1)", factorización de números semiprimos ;)

Espero te sirva. Saludos.


Título: Re: Problema al usar while
Publicado por: @XSStringManolo en 23 Abril 2020, 15:39 pm
 No entiendo para que tanto código para algo tan sencillo.
Ni las críticas del comentario sobre el do, que tu tampoco usas. Ni del static_cast que tampoco usas...


Código
  1. #include <iostream>
  2.  
  3.  
  4. using namespace std;
  5.  
  6.  
  7. int main() {
  8. int n = 1, i = 0, r = 0;
  9.  
  10.  
  11. while(n) {
  12.   cout << "Ingrese un número entero o 0 para salir." << endl;
  13.   cin >> n;
  14.  
  15.  
  16.   if(n) {
  17.     ++i;
  18.     cout << n << " * " << n << " - " << n << " = " << n*n-n << endl;
  19.     r += n*n-n;
  20.   }
  21. }
  22.  
  23.  
  24. cout << i << " numeros Ingresados." << endl <<
  25. "Suma de resultados calculados: " << r << endl;
  26.  
  27. cin.get();
  28. return 0;
  29. }

 
 


Título: Re: Problema al usar while
Publicado por: WHK en 23 Abril 2020, 21:45 pm
Porque 0 para factorización si es un número válido, solo te quisiste ahorrar la validación numérica.

saludos.


Título: Re: Problema al usar while
Publicado por: @XSStringManolo en 23 Abril 2020, 21:59 pm
Porque 0 para factorización si es un número válido, solo te quisiste ahorrar la validación numérica.

saludos.
Eso del 0 no lo sabía. Se puede meter un menú entonces antes de introducir el número. 1. Introducir número 2. Salir. O si quieres con letras. if(opcion == 'y') {} else if(opcion == 'n') {} else {cin >> opcion}


Más que nada es para no complicarle el código a alguien que empieza.


Título: Re: Problema al usar while
Publicado por: WHK en 23 Abril 2020, 22:13 pm
Citar
if(opcion == 'y') {}

No puedes hacer una comparación de un char de 1 dimension con un std::string, y cómo sabrías si el valor contiene otra letra y deba ser procesado para multiplicar o no?.


Título: Re: Problema al usar while
Publicado por: @XSStringManolo en 23 Abril 2020, 22:33 pm
No puedes hacer una comparación de un char de 1 dimension con un std::string, y cómo sabrías si el valor contiene otra letra y deba ser procesado para multiplicar o no?.
Es que no comparo con string. opcion es un char y 'y' también es un char literal.
Omito la comprobación porque considero que es innecesario para un programa sencillo para un usuario nuevo. En caso de necesitar forzosamente la comprobación usaría la función isDigit() de la librería ctype
 
http://www.cplusplus.com/reference/cctype/isdigit/


Título: Re: Problema al usar while
Publicado por: dijsktra en 25 Mayo 2020, 19:07 pm
Mas sencillo.
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4.  
  5. int main(int argc, char *args)
  6. {
  7.  int n,acum,many;
  8.  many=acum=0;
  9.  while (scanf("%d",&n)==1)
  10.    {
  11.      acum +=n;
  12.      many++;
  13.    }
  14.  if (ferror(stdin))
  15.    {
  16.      perror("scanf");
  17.      exit(1);
  18.    }
  19.  printf("\n%d %d\n",many,acum);
  20.  return 0;
  21. }
  22.  

Pruebas
Código:
 gcc stream.c -o main && ./main
10 20 30 40 50 n

5 150


Título: Re: Problema al usar while
Publicado por: Loretz en 25 Mayo 2020, 20:09 pm
¿dijsktra?

¿Puede ser que estés haciendo tu tributo jugando con el nombre del homenajeado?

https://www.britannica.com/biography/Edsger-Dijkstra (https://www.britannica.com/biography/Edsger-Dijkstra)



Título: Re: Problema al usar while
Publicado por: dijsktra en 25 Mayo 2020, 21:12 pm
¿dijsktra?

¿Puede ser que estés haciendo tu tributo jugando con el nombre del homenajeado?

https://www.britannica.com/biography/Edsger-Dijkstra (https://www.britannica.com/biography/Edsger-Dijkstra)



El mismo. Una figura apasionante. Con el (y otros más=, la programación pasó a tener rando de disciplina científica.

¿ Te interesa saber algo de él?
Entre otras cosas, te diré que fue un poco "tecnofobo", todos sus artículos los escrbía a manuscrito, ideo un método de sintésis de programas sistemático, conocido como la "derivación de programas".... Se oponía  a la programación con GOTOS, siendo el primer apóstol de la promgramación estructurada.

Tampoco le gustaba mucho la programación orientada a objetos, que consideraba "una aberración propia de Sillicon Valley..."

Solía decir. "Si depurar es el acto de encontrar fallos en un programa, entonces programar debe consistir en el acto de ponerlos dentro"...

Una vida apasionante....

https://www.youtube.com/watch?v=nVyqbfzOGI8 (https://www.youtube.com/watch?v=nVyqbfzOGI8)



Título: Re: Problema al usar while
Publicado por: Serapis en 26 Mayo 2020, 20:40 pm
Solo una puntualización acotada...
- Tienes un montón de variables que sobran, puedes reusar una para varias cosas o incluir en el cout la operación cuando no vayas a reusar una variable más.
Es muy mala práctica reusar variables, salvo ciertos casos.
Si se tiene una función con varios bucles uno tras otro, no hay problema alguno en reusar la variable que actúa de contador, pués ese es su propósito.

En cambio si tienes una variable como 'mes' definida por ejemplo como entero, que más adelante no la precises y la reutilices, solo enfanga el código... si tiempo más tarde tienes que revisarlo, podrías encontrarte con que 'mes = -3147', cuando su nombre sugiere que esté acotado en un valor 1-12 (por ejemplo).

En fin, ahorrar algunos bytes de memoria (hace 30-40 años tenía cierta validez, por la escasez de memoria, y aún así se desaconsejaba), lo más probable es que a futuro te malgaste tiempo (que es mucho más preciosos que algunos bytes sueltos) si se convierte en una práctica habitual, tratando de comprender que hace tal o cual variable aquí o allá y porque tiene valores dispares. Si cada variable es nombrada conforme a su propósito y no reutilizada fuera de dicho propósito, el código será siempre fácil de seguir o por lo menos no inducirá a errores, aunque pasen algunos años sin tocarlo...