Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: Juan821 en 9 Julio 2014, 03:56 am



Título: Temporizadores
Publicado por: Juan821 en 9 Julio 2014, 03:56 am
Como hago para luego de que pase un tiempo el programa haga lo que le ordene por ejemplo que deje digitar un numero por 60 segundos por ejemplo despues de esos 60 segundos no deje digitar nada y salgo un mensaje que me diga ha excedido su tiempo sera con clock() porque se que sleep puede que no sirva


Título: Re: Temporizadores
Publicado por: eferion en 9 Julio 2014, 08:33 am
¿Es un entorno de consola? ¿aplicación de escritorio? ¿usas alguna librería para la interfaz de usuario?

Tu pregunta, así planteada, es demasiado escueta.


Título: Re: Temporizadores
Publicado por: Juan821 en 14 Julio 2014, 22:37 pm
Es un programa normal en visual studio lo que trato de hacer es esto

Código
  1. cin>>x /* esto es para que digite algo y lo lea, lo que necesito es
  2. que si se pasan 60 segundos y no ha digitado nada salga el
  3. mensaje de que ha excedido su tiempo y ya siga con lo que
  4. hay abajo de esta linea como por ejemplo*/
  5.  
  6. if x==w printf("ha ganado");  


Título: Re: Temporizadores
Publicado por: Stakewinner00 en 14 Julio 2014, 23:10 pm
podrías crear un thread para escribir y un thread para contar el tiempo, en que estas, windows o linux?

también puedes cojer el reloj del PC y con un bucle ir comprobando si pasaron más de 60 segundos


Título: Re: Temporizadores
Publicado por: Juan821 en 15 Julio 2014, 20:19 pm
podrías crear un thread para escribir y un thread para contar el tiempo, en que estas, windows o linux?

también puedes cojer el reloj del PC y con un bucle ir comprobando si pasaron más de 60 segundos
estoy en windows entonces pero con un bucle como?


Título: Re: Temporizadores
Publicado por: eferion en 16 Julio 2014, 00:07 am
estoy en windows entonces pero con un bucle como?

la librería estándar de C++ no dispone de métodos que permitan una lectura no bloqueante sobre el buffer de entrada.

La opción sería crear una tarea con un hilo secundario que se encargase de realizar la lectura... en el hilo principal pones una espera activa hasta que pase el tiempo o el usuario introduzca un valor.... si se produce el timeout entonces matas el hilo secundario. Si antes de acabar el tiempo el usuario introduce un valor entonces dejas que el usuario introduzca su valor con normalidad y el programa continua.


Título: Re: Temporizadores
Publicado por: kutcher en 16 Julio 2014, 01:48 am
Como hago para luego de que pase un tiempo el programa haga lo que le ordene por ejemplo que deje digitar un numero por 60 segundos por ejemplo despues de esos 60 segundos no deje digitar nada y salgo un mensaje que me diga ha excedido su tiempo

Buenas, la unica forma que se me ocurre para lograr eso sin el uso de hilos, es haciendo uso de las funciónes kbhit() y getche() de la libreria conio.h

Código
  1. #include <iostream>
  2. #include <cstddef>
  3. #include <ctime>
  4. #include <conio.h>
  5.  
  6. bool get_input ( char *buffer, std::size_t size, int timeout )
  7. {
  8.    std::time_t start = std::time ( 0 );
  9.    std::size_t n = 0;
  10.  
  11.    for (;;)
  12.    {
  13.        if ( n == 0 && std::difftime (std::time(0), start ) >= timeout )
  14.            return false;
  15.  
  16.        if (kbhit()) {
  17.            if ( n == size - 1 )
  18.                break;
  19.            char ch = (int)getche();
  20.            if ( ch == '\r' )
  21.            {
  22.                buffer[n++] = '\n';
  23.                break;
  24.            }
  25.            else
  26.                buffer[n++] = ch;
  27.        }
  28.    }
  29.    buffer[n] = '\0';
  30.  
  31.    return true;
  32. }
  33.  
  34. int main(void)
  35. {
  36.    char buffer[20] = {};
  37.  
  38.    if ( !get_input (buffer, 20, 5) ) {
  39.        std::cout << "Tiempo agotado\n";
  40.        buffer[0] = '\n';
  41.    }
  42.    std::cout<<"\nSalida: " << buffer;
  43.  
  44.    return 0;
  45. }
  46.  

Se que la libreria conio.h no es recomendable utilizarla


Título: Re: Temporizadores
Publicado por: leosansan en 16 Julio 2014, 21:11 pm
...........................estoy en windows ..........................

Pues si estas en Windows podrías usar windows.h para "Sleep" y conio.h para kbhit:

Código
  1. #include <windows.h>
  2. #include <iostream>
  3. #include <conio.h>
  4. #include <iomanip>
  5.  
  6. using namespace std;
  7.  
  8. int main(){
  9.  int i , ss = 5 , algo = 0 ;
  10.  while( !kbhit() ){
  11.    for( i = ss ; i>= 0 ; i-- ){
  12.      if (kbhit()){
  13.        cout << endl;
  14.        break;
  15.      }
  16.    Sleep(1000);
  17.    cout << "Quedan: " << setw(2) << i << " segundos.\r" ;
  18.    }
  19.    if ( i == -1 ) break;
  20.  }
  21.  if ( i> -1){
  22.    cin >> algo;
  23.    cout << endl << "algo= " << algo << endl;
  24.  }
  25.  else cout << endl << "Tiempo excedido\n" << endl;
  26.  return 0;
  27. }

Y reitero lo de kutcher, sí ya sé que no es aconsejable usar conio, pero no se me apetece meterme ahora con las API de Windows.   ;)

¡¡¡¡ Saluditos! ..... !!!!


(http://st.forocoches.com/foro/images/smilies/aaaaa.gif)



Título: Re: Temporizadores
Publicado por: Juan821 en 17 Julio 2014, 20:02 pm
Pues si estas en Windows podrías usar windows.h para "Sleep" y conio.h para kbhit:

Código
  1. #include <windows.h>
  2. #include <iostream>
  3. #include <conio.h>
  4. #include <iomanip>
  5.  
  6. using namespace std;
  7.  
  8. int main(){
  9.  int i , ss = 5 , algo = 0 ;
  10.  while( !kbhit() ){
  11.    for( i = ss ; i>= 0 ; i-- ){
  12.      if (kbhit()){
  13.        cout << endl;
  14.        break;
  15.      }
  16.    Sleep(1000);
  17.    cout << "Quedan: " << setw(2) << i << " segundos.\r" ;
  18.    }
  19.    if ( i == -1 ) break;
  20.  }
  21.  if ( i> -1){
  22.    cin >> algo;
  23.    cout << endl << "algo= " << algo << endl;
  24.  }
  25.  else cout << endl << "Tiempo excedido\n" << endl;
  26.  return 0;
  27. }

Y reitero lo de kutcher, sí ya sé que no es aconsejable usar conio, pero no se me apetece meterme ahora con las API de Windows.   ;)

¡¡¡¡ Saluditos! ..... !!!!


(http://st.forocoches.com/foro/images/smilies/aaaaa.gif)



ya lo probe si sirve pero el problema es que si le dan a una letra y no le dan enter
se pausa la cuenta regresiva he intentando arreglarlo pero no he sido capas aunque muchas gracias que con esto seguire averiguando para perfeccionarlo gracias


Título: Re: Temporizadores
Publicado por: vangodp en 18 Julio 2014, 10:12 am
la librería estándar de C++ no dispone de métodos que permitan una lectura no bloqueante sobre el buffer de entrada.

La opción sería crear una tarea con un hilo secundario que se encargase de realizar la lectura... en el hilo principal pones una espera activa hasta que pase el tiempo o el usuario introduzca un valor.... si se produce el timeout entonces matas el hilo secundario. Si antes de acabar el tiempo el usuario introduce un valor entonces dejas que el usuario introduzca su valor con normalidad y el programa continua.
¿Puedes brindarnos un ejemplo sencillo y/o alguna pagina/pdf/tutorial o lo que sea sobre el tema?
He leído sobre POSIX no POSIX y la verdad es que menudo lio eso de los trheads y procesos.
Pinta bien pero no veas si raya jejeje.


Título: Re: Temporizadores
Publicado por: eferion en 18 Julio 2014, 12:49 pm
No es un mecanismo excesivamente depurado pero sirve para la ocasión:

Lo primero que necesitamos es una clase que nos permita "controlar" la entrada del teclado.

Para nuestra desgracia, el estándar de C++ no ayuda, ya que los mecanismos de entrada no van a devolver ningún dato hasta que el usuario presione la tecla "enter". Por este motivo nos tenemos que pegar con mecanismos menos portables... para la ocasión he usado la tan odiada "conio". Si alguien se lo quiere currar más está en su perfecto derecho.

El método run de la clase es bastante simple... cuando se presiona una tecla, activa un flag que indica la intención del usuario de introducir un número... cuando se introduce un carácter se actualiza el número introducido (esta versión no admite backspace)... cuando se introduce un enter se almacena el número y se sale de la función.

Código
  1. class DataManager
  2. {
  3.  public:
  4.  
  5.    DataManager( ) = default;
  6.  
  7.    DataManager( const DataManager& ) = delete;
  8.  
  9.    ~DataManager( ) = default;
  10.  
  11.    void Run( )
  12.    {
  13.      int temp_number = 0;
  14.  
  15.      while ( true )
  16.      {
  17.        char c = getch( );
  18.        _withData = true;
  19.  
  20.        if ( c != '\n' && c != '\r' )
  21.        {
  22.          std::cout << c;
  23.          temp_number *= 10;
  24.          temp_number += c - '0';
  25.        }
  26.        else
  27.        {
  28.          std::cout << std::endl;
  29.          _number = temp_number;
  30.          break;
  31.        }
  32.      }
  33.    }
  34.  
  35.    bool WithData( ) const
  36.    { return _withData; }
  37.  
  38.    int Number( ) const
  39.    { return _number; }
  40.  
  41.    const DataManager& operator=( const DataManager& ) = delete;
  42.  
  43.  private:
  44.  
  45.    bool _withData = false;
  46.    int _number = 0;
  47. };

Después necesitamos una clase para llevar de forma sencilla el conteo del tiempo... algo del tipo:

Código
  1. class Timer
  2. {
  3.  public:
  4.    using milliseconds = std::chrono::milliseconds;
  5.  
  6.    Timer( )
  7.    {
  8.      Reset( );
  9.    }
  10.  
  11.    Timer( const Timer& ) = delete;
  12.  
  13.    ~Timer( ) = default;
  14.  
  15.    void Reset( )
  16.    {
  17.      _start = std::chrono::high_resolution_clock::now( );
  18.    }
  19.  
  20.    milliseconds Elapsed( ) const
  21.    {
  22.      return std::chrono::duration_cast< milliseconds >( std::chrono::high_resolution_clock::now( ) - _start );
  23.    }
  24.  
  25.    const Timer& operator=( const Timer& ) = delete;
  26.  
  27.  private:
  28.    std::chrono::high_resolution_clock::time_point _start;
  29. };

Cuando se crea la clase se registra el tiempo y llamando a "Elapsed" se devuelve el número de milisegundos desde ese instante. Reset vuelve a inicializar la clase.

Con estos ingredientes ya tenemos casi todo el trabajo echo... solo nos falta mezclarlos convenientemente en el main:

Código
  1. int main( )
  2. {
  3.  std::cout << "Introduce un numero." << std::endl;
  4.  std::cout << "Tienes 5 segundos para empezar" << std::endl;
  5.  
  6.  DataManager manager;
  7.  
  8.  std::thread thread{ [](DataManager* mgr){ mgr->Run( ); }, &manager };
  9.  
  10.  Timer timer;
  11.  while ( timer.Elapsed( ) < std::chrono::seconds{ 5 } )
  12.  {
  13.    if ( manager.WithData( ) )
  14.      break;
  15.  }
  16.  
  17.  if ( !manager.WithData( ) )
  18.    thread.detach( );
  19.  else
  20.    thread.join( );
  21.  
  22.  if ( manager.WithData( ) )
  23.    std::cout << "Has introducido el numero: " << manager.Number( ) << std::endl;
  24.  else
  25.    std::cout << "No has introducido ningun numero." << std::endl;
  26. }

Para controlar la entrada del teclado se crea un hilo. Después se inicializa el temporizador y se mantiene una espera activa de 5 segundos. La idea del temporizador en vez de un sleep es para que la aplicación pueda responder instantáneamente si el usuario introduce el número antes de 5 segundos.

Pasado el tiempo de espera activa se comprueba si el usuario ha hecho al menos el amago de introducir un número... si es así entonces espera pacientemente a que el usuario termine de introducir el número... en caso contrario finaliza el hilo y muestra el mensaje correspondiente.

Como he comentado antes, es algo muy mejorable. El ejemplo lo he realizado a petición de vangodp y sirve solo con fines ilustrativos.

PD.: utiliza funciones propias de C++11, ojo con los compiladores no compatibles.


Título: Re: Temporizadores
Publicado por: leosansan en 18 Julio 2014, 16:56 pm
Sin conio.h pero con:

Código
  1. #include <windows.h>
  2. #include <iostream>
  3. #include <iomanip>
  4. #include <unistd.h>
  5. #include <pthread.h>

Creo un hilo para el contador, que sigo usando Sleep por ganseria en lugar de cronos, y poco más. Sólo que el "Quedan" podemos evitarlo ya que distorsiona un poco la impresión. Pero bueno, como intento sin usar conio y que no espere hasta que se dé al ENTER creo que vale.....y ojo que no soy especialista en hilos, así que las críticas suaves, please  ;)

Código
  1. using namespace std;
  2.  
  3. void *hilo1(void *X){
  4.  int i , ss = 10 ;
  5.  cout << "Creando hilo " << endl;
  6.  while( 1 ){
  7.    for( i = ss ; i>= 0 ; i-=2 ){
  8.      Sleep(2000);
  9.    cout << "   Quedan: " << setw(2) << i << " segundos.\r"  ;
  10.    }
  11.    if ( i == -1 ) break;
  12.  }
  13.  cout << endl << "Tiempo excedido\n" << endl;
  14.  exit(1) ;
  15. }
  16.  
  17. int main(){
  18.  int  algo = 0 ;
  19.  pthread_t hilo ;
  20.  pthread_create (& hilo , NULL , hilo1 , NULL );
  21.  cout << endl << "No te olvides del ENTER " << endl;
  22.  cin >> algo ;
  23.  cout << endl << endl << "algo = " << algo << endl;
  24.  return 0;
  25. }

¡¡¡¡ Saluditos! ..... !!!!


(http://st.forocoches.com/foro/images/smilies/aaaaa.gif)