5

We know input function or operator (cin, scanf,gets….etc) wait to take input form user & this time has no limit.

Now, I will ask a question & user give the answer, till now there no problem but my problem is “user has a time(may 30 or 40 sec) to give the input, if he fail then input statement will automatically deactivated & execute next statement.”

I think you get my problem. Then please help me in this situation. It will be better if someone give me some really working example code.

I use codebolck 12.11 in windows 7.

tshepang
  • 12,111
  • 21
  • 91
  • 136
Xplosive
  • 711
  • 3
  • 14
  • 26
  • 4
    The standard C++ has nothing to help you. You need to employ some more or less evil OS-specific tricks. – n. m. could be an AI Aug 17 '13 at 14:09
  • 1
    thanks for your reply. Can you give me some kind of example or function, please. – Xplosive Aug 17 '13 at 14:11
  • No, because I don't know what your OS is. – n. m. could be an AI Aug 17 '13 at 14:13
  • 1
    this link would be helpful. Here you will found another two links those links consists snippets in different languages and also some sort of explanation. http://bytes.com/topic/c-sharp/answers/626475-setting-timeout-console-readline – Gangadhar Aug 17 '13 at 14:31
  • 1
    my os is windows 7 & compiler is codeblock 12.11 – Xplosive Aug 17 '13 at 17:25
  • CodeBlocks isn't a compiler, but an IDE. It can use different compilers, depending on how it is configured. – alk Aug 17 '13 at 18:05
  • The difference in behaviuor of *nishant*'s solution and mine discovered some kind missing specification to your use-case: Does the time-out refer to the **first** or the **last** character entered by the user? – alk Aug 18 '13 at 08:21

3 Answers3

10

An approach for *IX'ish systems (including Cygwin on windows):

You could use alarm() to schedule a SIGALRM, then use read(fileno(stdin), ...).

When the signal arrives read() shall return with -1 and had set errno to EINTR.

Example:

#define _POSIX_SOURCE 1

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>

void handler_SIGALRM(int signo)
{
  signo = 0; /* Get rid of warning "unused parameter ‘signo’" (in a portable way). */

  /* Do nothing. */
}

int main()
{
  /* Override SIGALRM's default handler, as the default handler might end the program. */
  {
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));

    sa.sa_handler = handler_SIGALRM;

    if (-1 == sigaction(SIGALRM, &sa, NULL ))
    {
      perror("sigaction() failed");
      exit(EXIT_FAILURE);
    }
  }

  alarm(2); /* Set alarm to occur in two seconds. */

  {
    char buffer[16] = { 0 };

    int result = read(fileno(stdin), buffer, sizeof(buffer) - 1);
    if (-1 == result)
    {
      if (EINTR != errno)
      {
        perror("read() failed");
        exit(EXIT_FAILURE);
      }

      printf("Game over!\n");
    }
    else
    {
      alarm(0); /* Switch of alarm. */

      printf("You entered '%s'\n", buffer);
    }
  }

  return EXIT_SUCCESS;
}

Note: In the example above the blocking call to read() would be interupted on any signal arriving. The code to avoid this is left as an execise to the reader ... :-)

alk
  • 69,737
  • 10
  • 105
  • 255
3

Another Method:
You can use POSIX select() function (and some macros FD_ZERO, FD_SET, FD_ISSET) to check which file descriptors (descriptor number 0 i.e. stdin, in this case) are ready to be read in a given time interval. When they are ready, use appropriate function to read the data (scanf() in this case).
This code might help you understand, what I want to say:

#include <sys/select.h>
#include <sys/time.h>
#include <stdio.h>

#define STDIN    0    // Standard Input File Descriptor
int main()
{
    fd_set input;       // declare a "file descriptor set" to hold all file descriptors you want to check
    int fds, ret_val, num;  // fds: Number of file descriptors;

    struct timeval tv;      // structure to store Timeout value in the format used by select() function
    unsigned int timeout = 5;   // Your timeout period in seconds

    tv.tv_sec = timeout;    
    tv.tv_usec = 0;

    fds = STDIN + 1;            // Set number of file decriptors to "1 more than the greatest file descriptor"
                // Here, we are using only stdin which is equal to 0

    FD_ZERO(&input);        // Initialize the set with 0
    FD_SET(STDIN, &input);      // Add STDIN to set

    printf("Enter a number within %d secs\n", timeout);
    ret_val = select(fds, &input, NULL, NULL, &tv); 
                // We need to call select only for monitoring the "input file descriptor set"
                // Pass rest of them as NULL

    if (ret_val == -1)          // Some error occured
        perror("select()");
    else if (ret_val > 0)       // At least one of the file descriptor is ready to be read
    {
//      printf("Data is available now.\n");
        if(FD_ISSET(0, &input))     // Check if stdin is set, here its not necessary as we are using STDIN only
                // So ret_val>0 means STDIN is raedy to read 
        {
            scanf("%d", &num);
        }
    }
    else
        printf("No data within five seconds.\n");   // select returns zero on timeout

    return 0;
}

More Help: select(2)

You can also try using poll() function available in (again a POSIX standard function) as an alternative to select(). See poll() & poll(2)

0xF1
  • 6,046
  • 2
  • 27
  • 50
  • 3
    I just wanted to make the same suggestion. (Sometimes you might want to handle EINTR at the `ret_val == -1` clause though.) For porting this to Windows have a look at this question: http://stackoverflow.com/q/933745/1025391 – moooeeeep Aug 17 '13 at 18:45
  • Thanks @moooeeeep for the link !! I was also wondering how similar code can work under Windows based system. I forgot to mention this non-portability in my answer. – 0xF1 Aug 17 '13 at 18:55
  • 1
    #include #include my compiler can't find such of header file. i use codebolck 12.11 – Xplosive Aug 18 '13 at 05:46
  • 1
    Which OS do you use? As pointed out by @moooeeeep, this will work only on UNIX based system "having POSIX libraries" (you can check that using `man select`, `man pselect`, etc., if the help shows up, you have the libraries), for Windows, you can follow the link posted by him. – 0xF1 Aug 18 '13 at 06:30
  • @Xplosive: Also do check for proper path to the libraries and if they are not on default path, specify using `-L` option to `gcc`. – 0xF1 Aug 18 '13 at 06:37
0
#include <cstddef>
#include <ctime>
#include <iostream>
#include <conio.h>

bool get_input ( char *buffer, std::size_t size, int timeout )
{
     std::time_t start = std::time ( 0 );
     std::size_t n = 0;

   for ( ; ; ) {
    if ( n == 0 && std::difftime ( std::time ( 0 ), start ) >= timeout )
     return false;

    if ( kbhit() ) {
  if ( n == size - 1 )
    break;

  char ch = (int)getche();

  if ( ch == '\r' ) {
    buffer[n++] = '\n';
    break;
  }
  else
    buffer[n++] = ch;
  }
}

 buffer[n] = '\0';

return true;
}

 int main()
{
char buffer[512] = {0};

if ( !get_input ( buffer, 512, 5 ) ) {
std::cout<<"Input timed out\n";
buffer[0] = '\n';
}

std::cout<<"input: \""<< buffer <<"\"\n";
}
Akshay
  • 1
  • i run this code in code blocks 13.2 its working fine after some time interval the program is ending automatically using this code is there any possible to use it for cin ???? – Akshay Aug 24 '14 at 14:51
  • This code use non Standard-C, non-POSIX functionality, and with this is high unportable. – alk Aug 31 '15 at 10:34