¿Parar un bucle for pulsando una tecla?

Iniciado por jmhr98, 17 Agosto 2018, 22:07 PM

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

jmhr98

¿Alguien sabe alguna forma de hacerlo? He usado un condicional if en el ciclo for. De la forma: if(cin.get()=='d') Return 0; pero el bucle se queda esperando a que yo pulse alguna otra tecla. Es decir, lo que quiero es que el bucle se vaya ejecutando y cuando yo pulse la d, se termine el programa. No que se quede esperando a que yo pulse la d u otra para funcionar y volver al mismo punto de pedirme otra vez que introduzca otra tecla. Gracias

MAFUS

Para eso debes cambiar el modo de trabajo del terminal. En el compilador de Borland eso lo hacía getch pero puedes emularlo. Busca en Google, o por el foro ya que también se ha tocado este tema, cómo emular getch en windows o linux, según sea tu sistema operativo.

jmhr98

Entré en el mundo de la programación y el C++ hace unos días. No sé a qué se refiere. Pero si consiguiese eso, ¿Podría poner ese condicional y no pararse hasta que introduzca un carácter?
Sí me pudiese ser más concreto y ayudarme, se lo agradecería mucho.

ThunderCls

Has probado tu codigo de comprobacion en un nuevo hilo?

Código (cpp) [Seleccionar]
while(true)
{
   if(cin.get()=='d')
      exit(0);
   Sleep(10);
}
-[ "...I can only show you the door. You're the one that has to walk through it." – Morpheus (The Matrix) ]-
http://reversec0de.wordpress.com
https://github.com/ThunderCls/

MAFUS

getch es  una forma de conseguir una tecla sin que se detenga el programa para que el usuario haga la entrada, es decir, si no se produce una pulsación el programa continua, y si se produce el programa continuará y getch te retornará que se ha pulsado. Además no producirá eco en la pantalla.

Implementación para windows:
https://helloacm.com/modern-getch-implementation-on-windows-cc/

Implementación para linux:
https://stackoverflow.com/questions/7469139/what-is-equivalent-to-getch-getche-in-linux

jmhr98

#5
Getch es para detectar si se ha pulsado una tecla o no. No entiendo la función que tendría en el hecho de detener el programa. ThunderCls, he usado tu código y no funciona.
Para que entendáis mi problema, éste es el código:



Código (cpp) [Seleccionar]


#include "iostream"
#include "conio.h"
#include "time.h"
using namespace std;
int main(){
  srand(time(NULL));
int Y,num=10;
     int n[11]={0,1,2,3,4,5,6,7,8,9,10};
     Y=rand()%num;
  for (int i=0; i<10;i++){
        if (i==Y){
     cout <<"\033[1;35m\033[1m" << n[i] << "\033[1;35m\033[0m"<<endl;  
     }
        else{   cout << n[i]<<endl;  
     
     sleep(1);
   
  if {(cin.get()=='d')
      return 0;}
 
  }
  }
return 0;  

}

[/quote]


Para que entiendan como es el funcionamiento normal que quiero para el programa (cuenta atrás y un número aleatorio se torna de un determinado color), quiten la parte del condicional if que lleva el cin.get.

Gracias por sus mensajes y ayuda. Es que me estoy desanimando de seguir aprendiendo porque no entiendo nada.

Serapis

#6
De entrada, C tiene una curvatura de aprendizaje muy muy larga, así que o se tiene paciencia, o es mejor saltar a otro lenguaje... Además si uno accede a C, sin conocimientos previos de ningún tipo, es manifiestamente más complicado, porque se rodea de demasiada jerga que complica al no iniciado.

Si dentro de un bucle pones una llamada que interrogue al usuario para pulsar una tecla, evidentemente el suceso es que se detiene la ejecución en ese punto hasta recibir una pulsación de tecla....

Así que, en efecto, esa funconalidad no te sirve si lo que pretendes es que se ejecute sin pausa y salga cuando se pulse determinada tecla.

El driver del teclado, almacena en un búfer las teclas que se van pulsando y el sistema operativo, obtiene información sobre el búfer mediante interrupciones, cuando se detecta que hay nuevas pulsaciones, las aplicaciones que se 'enganchen', reciben una notificación, donde se señala el código de la tecla pulsada y algún detalle extra.

Por ejemplo, si una aplicación tiene interfaz de usuario, cada control de la interfaz gráfica que tenga eventos de teclado, se engancha a dichas funciones y son notificadas... la forma en que el usuario interacciona en dicho caso es muy similar al getch.

Básicamente una función recibe la notificación y dentro se examina si se dan las condiciones que se desean... y se activa algún flag que se consulta en otra parte (o s e lanza un evento en caso de objetos, para notificar a otros objetos que estén enganchados a dichas notificaciones)

funcion NotificacionTeclado( entero codigo, entero flags) //flags puede ser indicadores del tipo del estado de las teclas ALT, Mayusculas, CTRL, etc...
   Si codigo = codigoquemeinteresa luego
       codigoEntrado = TRUE
   fin si
fin funcion


Y tu bucle lo condicionas a la espera de dicho suceso (o añadido a otras condiones si hay más)


... otra función en alguna parte

codigoquemeinteresa = ???? //el que tu veas preciso...
bucle ....
  ...loque sea que haga el bucle
repetir mientras codigoEntrado = FALSE  // and ....otras condiciones
codigoEntrado = FALSE  // se desactiva la bandera salvo que se requiera algo más adelante...


Lo que te señala Mafus, de getch es para hacer la parte que en el pseudocódigo se señala como función...
Nota que codigoEntrado se declara de tipo buleano a nivel del módulo lo mismo que 'codigoquemeinteresa', que ha de contener el valor del código que tu esperas (el valor asociado a la tecla 'd' (con ayuda de un flag, sabrás si es 'd' ó 'D'...)



De todos modos si estás empezando, aprendiendo, debes hacerlo con código que entiendas de cabo a rabo, e ir avanzando poco a poco...

Más adelante, cuando ya tengas una base mínima del lenguaje (el tiempo transcurrido para esto es relativo, ya que cada cual aprende a su ritmo y cada cual dedica el tiempo que quiere-puede) ya entonces con ejemplos más complejos, aunque parte del código no lo entiendas.
A menudo al poner un ejemplo para explicar algo, o se pone un ejemplo demasiado tonto, o fuerza a ponerse algo más ameno a cambio de exponer cosas que aún no se hayan dado... en los ejemplos, quédate con la parte que comenta el libro, tutorial, curso que estés leyendo/siguiendo/dando, ya llegará la parte en que explique aquello que en dicho instante queda oscuro...

MAFUS

En C no hay una entrada directa desde el teclado. Hay un buffer, algo así como un contenedor, que se va llenando a medida que se van pulsando teclas y el lenguaje cuándo captura las entradas del teclado lo que hace es sacar del buffer lo que se ha ido introduciendo en el mismo orden.

Por otra parte C es un lenguaje próximo a la máquina así que depende mucho de cómo funcione el hardware, en su defecto, de cómo lo gestione el sistema operativo.

De normal lo que hace el sistema operativo es si le han pedido algo desde el teclado y el buffer está vacío detendrá el programa hasta que alguien pulse una tecla, entonces entregará esa tecla pulsada, la mostrará por pantalla y continuará con la ejecución el programa. Pero este comportamiento se puede cambiar y eso es lo que muestran los dos enlaces que te he pasado: allí el programa seguirá corriendo aún haya petición y el buffer esté vacío. También, si se va llenando no existirá aviso sino que en el momento que se pida una tecla pulsada ésta se entregará si hay petición. Y de hecho esto es lo que buscas en tu programa.

Pero me quedo con lo que te ha dicho NEBIRE: sigue aprendiendo el lenguaje, quizás con programas más básicos que no requieran estos efectos. Una vez lo domines podrás escalar de nivel. Ya ves que C depende de en qué máquina te encuentres. Otros lenguajes son más portables porque todo el framework que los soporta los ha alejado mucho de la máquina, en cambio C es un lenguaje muy básico y su framework es básicamente el sistema entero.

jmhr98

Sí, MAFUS, es cierto todo. Pero es que ando sin guía y es un amigo el que me hace esta especie de retos. Así voy aprendiendo mientras buscó (como he aprendido el tema de poner colores a los caracteres y demás). Pero si no paso "esta pantalla", no puedo seguir sus peticiones. No sé, leí la página pero no entendí nada. Es por ello que quizás era lo que buscaba, pero por falta de conocimiento no me dí cuenta. ¿Sabes de alguna guía? ¿Y como de usaría lo de la web que me recomendaste? Estoy pensando que antes del for almacenar en el buffer un carácter y así no se defendía el bucle? Es eso lo que quieres decir?

MAFUS

#9
Intentando resolver tu problema me he encontrado con que la solución es más sencilla, en Windows:
https://msdn.microsoft.com/es-es/library/windows/desktop/ms646301(v=vs.85).aspx

resultando el siguiente código  (no lo mires si quieres hacerlo tu mismo):



#include <stdio.h>
#include <windows.h>

int main() {
   for(unsigned i=0; !(GetKeyState(0x44)&0x80); ++i)
       printf("%i\n", i);
}