Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: el_nene_kpy en 4 Febrero 2012, 23:18



Título: DUDA impresion caracter a caracter con retardo (C)
Publicado por: el_nene_kpy en 4 Febrero 2012, 23:18
Buenas a todos,

soy nuevo en este foro, asi que pido que no me crucifiquen en caso de equivocarme de lugar al crear el hilo.

Tengo que realizar un programa que al imprimir por pantalla cualquier frase lo haga como si fuese una persona escribiendo, es decir, que no plante la frase entera directamente, sino que vaya letra a letra con un pequeño retardo.
He estado bucando por todas las funciones que incluye ANSI C (programo en Ubuntu con NetBeans, y tengo que compilar con make y ejecutar desde terminal) pero no encuentro absolutamente ninguna funcion ni forma de hacerlo.

Me urge ya que tengo que entregarlo en un trabajo dentro de dos dias, asi que toda ayuda sera agradecida.

Muchas gracias


Título: Re: DUDA impresion caracter a caracter con retardo (C)
Publicado por: eleon en 5 Febrero 2012, 00:07
La velocidad del ordenador siempre va a hacer que se imprima "de golpe" a nuestros ojos. La forma de hacer lo que planteas es marcarle las pautas explícitamente, es decir, imprimir un caracter y decírle que espere x segundos. Aqui un ejemplo con la función "Sleep ()" de la librería "windows.h":

Código
  1. #include <iostream>
  2. #include <windows.h>
  3. using namespace std;
  4.  
  5. int main ()
  6.  
  7. {
  8.    char cadena [17] = "Esto es un texto";
  9.  
  10.    for (int i = 0; i < 16; i++)
  11.    {
  12.        cout << cadena [i];
  13.        Sleep(200);
  14.    }
  15.  
  16.    cin;
  17.    return 0;
  18. }

Nota 1: La inicial de "Sleep" se escribe con mayúscula.
Nota 2: Dentro se ponen los milisegundos que quieres que se pause el programa (1000 ms = 1 s).

Ami particularmente no me gusta esta función porque como se puede observar haces que el programa sea dependiente de windows (por la librería). Si quieres mantener el programa de forma multiplataforma busca acerca de la librería "time" que creo que también viene con una función similar.

Saludos.


Título: Re: DUDA impresion caracter a caracter con retardo (C)
Publicado por: el_nene_kpy en 5 Febrero 2012, 00:24
La velocidad del ordenador siempre va a hacer que se imprima "de golpe" a nuestros ojos. La forma de hacer lo que planteas es marcarle las pautas explícitamente, es decir, imprimir un caracter y decírle que espere x segundos. Aqui un ejemplo con la función "Sleep ()" de la librería "windows.h":

Código
  1. #include <iostream>
  2. #include <windows.h>
  3. using namespace std;
  4.  
  5. int main ()
  6.  
  7. {
  8.    char cadena [17] = "Esto es un texto";
  9.  
  10.    for (int i = 0; i < 16; i++)
  11.    {
  12.        cout << cadena [i];
  13.        Sleep(200);
  14.    }
  15.  
  16.    cin;
  17.    return 0;
  18. }

Nota 1: La inicial de "Sleep" se escribe con mayúscula.
Nota 2: Dentro se ponen los milisegundos que quieres que se pause el programa (1000 ms = 1 s).

Ami particularmente no me gusta esta función porque como se puede observar haces que el programa sea dependiente de windows (por la librería). Si quieres mantener el programa de forma multiplataforma busca acerca de la librería "time" que creo que también viene con una función similar.

Saludos.


Ya he estado investigando la libreria time.h y no he encontrado ninguna. Puede ser porque la web este incompleta o porque no pertenezca a ella. Buscare en otras web para asegurarme igualmente.
Gracias


Título: Re: DUDA impresion caracter a caracter con retardo (C)
Publicado por: eleon en 5 Febrero 2012, 00:37
He investigado un poco por mi parte y las librerías time.h/ctime no tienen función de pausa implementadas sino que se usan funciones incluidas en ellas para crearla. Es muy sencillo aqui tienes una guía: http://codigoc.org/481-funcion-delay-en-c

Saludos.


Título: Re: DUDA impresion caracter a caracter con retardo (C)
Publicado por: el_nene_kpy en 5 Febrero 2012, 01:06
He investigado un poco por mi parte y las librerías time.h/ctime no tienen función de pausa implementadas sino que se usan funciones incluidas en ellas para crearla. Es muy sencillo aqui tienes una guía: http://codigoc.org/481-funcion-delay-en-c

Saludos.

He intentado realizar lo que dice en la web citada, adaptandolo de c++ a c, y no me ha funcionado. Gracias


Título: Re: DUDA impresion caracter a caracter con retardo (C)
Publicado por: eleon en 5 Febrero 2012, 01:12
Código
  1. #include <time.h>
  2. #include <stdio.h>
  3.  
  4. void delay(int secs)
  5. {
  6.    int i;
  7.    for(i = (time(NULL) + secs); time(NULL) != i; time(NULL));
  8. }
  9.  
  10. int main()
  11. {
  12.    int sec;
  13.    printf ("Segundos a pausar: ");
  14.    scanf ("%d", &sec);
  15.    delay(sec);
  16. }


Título: Re: DUDA impresion caracter a caracter con retardo (C)
Publicado por: satu en 5 Febrero 2012, 02:21
Hola

Hace poco tuve un problema parecido y esta fue la solución:
Código
  1. void delay(double seconds)
  2. {
  3.    time_t start, end; //time.h
  4.    double dif;
  5.  
  6.    time(&start);
  7.    do{
  8.        time(&end);
  9.    }
  10.    while(difftime(end, start) < seconds);
  11. }
  12.  

Prueba a ver si te funciona

Saludos


Título: Re: DUDA impresion caracter a caracter con retardo (C)
Publicado por: ~ en 5 Febrero 2012, 02:30
Una forma simple y portable, que no depende de ninguna librería, es simplemente usar un bucle vacío con una variable entera que disminuya hasta llegar a cero para "gastar tiempo" y producir una temporización.

El único problema es que el tiempo es muy variable entre diferentes velocidades de CPU, en la pequeña escala (milisegundos o microsegundos), y a veces también a gran escala (décimas de segundo o centésimas de segundo).

Hay que tener cuidado: un valor de la variable muy alto se tardaría demasiado, y un valor muy bajo produciría una temporización demasiado corta para, por ejemplo, simular escribir en un teclado a la velocidad "natural".

Para este problema, puede que esto sea lo más simple, ya que es capaz de esperar menos de 1 segundo entre caracteres, que es más natural para alguien que escribe relativamente rápido.

Lo realmente ideal es usar las funciones de temporización de cada sistema operativo, y si se usa C (que internamente también usa las librerías de cada sistema en que está implementado) lo normal es escribir o usar una función existente que permita esperar milisegundos en lugar de segundos (1000 milisegundos son 1 segundo), porque eso es lo verdaderamente práctico, útil y necesario, en programación de producción.

Código:
#include <stdio.h>
#include <time.h>


void delayerloop(void);


int main(void)
{
 //Declarar nuestro contador de bucle de cadena,
 //nuestra cadena, y la longitud de la cadena:
 ///
  int n;
  char s[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  int slen=sizeof(s);


 //Mostrar cada carácter con un retardo.
  for(n=0;n<slen;n++)
  {
   //Retardar:
   ///
    delayerloop();

   //Poner un carácter en 'stdout' (salida estándar o consola
   //de texto en este caso):
   ///
    putchar(s[n]);


   //Forzar escribir el carácter ya. Si esto no se usa, el
   //carácter no se mostrará de manera inmediata:
   ///
    fflush(stdout);
  }

  return 0;
}




//Esta función se vale de un bucle con un contador
//expresado con números hexadecimales para provocar un
//pequeño retraso, sin usar ninguna librería.
//
//Esto es muy simple y portable en teoría, pero el tiempo
//que se tardará en cuestión dependerá de la velocidad
//de cada CPU en el que se corra, que puede ser más o menos
//lento.
///
void delayerloop(void)
{
 //Esto se puede cambiar al valor que deseemos
 ///
  register long x=0x8FFFFFF;


 //Efectuar la temporización:
 ///
  while(x--);
}


Título: Re: DUDA impresion caracter a caracter con retardo (C)
Publicado por: Xandrete en 5 Febrero 2012, 03:43
Psché. Y si no, al carajo la portabilidad. En linux puedes usar esto (http://www.chuidiang.com/clinux/senhales/senhales.php#alarmas). La función alarm es un poco tosca y sólo admite tiempos múltiplos de 1 segundo. La función setitimer es mucho más sofisticada y te permite implementar temporizadores con tiempos que van desde los microsegundos. El tema de los temporizadores... veo complicado que encuentres una solución portable decente. Lo digo porque para implementar un temporizador, sueles depender de los servicios y llamadas al sistema de los que te provee el SO. No digo que no puedas encontrar ninguna solución portable y que use la librería estándar. Está la de satu. Sin embargo, no me gusta mucho esta última por algo que detallaré más adelante.

Lo de usar un bucle a modo de temporizador, como propone ~, no es muy buena idea. Una de las razones las da el propio ~. Otro inconveniente es que consume tiempo de cálculo y mantiene la CPU ocupada. Lo mismo con la solución de satu: consume tiempo de cálculo innecesario (y además, realiza llamadas al sistema constantemente). Es mejor usar funciones bloqueantes, aunque ello signifique perder en portabilidad, porque es un desperdicio de recursos tener un programa en Run o en la cola de Ready que sólo está esperando. Y si no, se pueden usar librerías de terceros que estén disponibles para varios SO y que ofrezcan temporizadores. O implementar uno mismo esas librerías para los SO a los que se piensa dirigir el programa (en este ejemplo, se podría implementar el temporizador con sleep para Windows y con setitimer para Linux). De esa forma, el código sería portable, pero no se limitaría a la librería estándar. No obstante, la solución de satu es perfectamente válida si tu código tiene únicamente fines académicos o es para uso propio, pero no es algo que yo recomendaría para proyectos profesionales.

Saludos