5

I'm just wondering whether is it possible and how do I implement this feature, where we exit from the loop if there's no input from the user. For example, I want to exit the loop if the user does not input anything after 1 minute. Here's my C code :

#include <stdio.h>
#include <conio.h>
#include <time.h>

int main(void)
{
    int x;
    time_t end = time(0) + 60;
    printf("Enter a number : ");

    while (time(0) < end)
    {
        if((scanf("%d", &x)) != EOF || (getchar() != '\n'))
        {
            time_t end2 = time(0) + 60;
            while(time(0) < end2);
            main();
        }
        else
        {
            printf("%d", x);
            main();
        }
    }
    main();
}
Jitzu Zu
  • 71
  • 1
  • 1
  • 4
  • 3
    What's with all the recursion? – SpacedMonkey Nov 21 '12 at 10:42
  • 2
    Try to avoid using conio.h library, because it's not an standard library of C and it only works in Borland C compiler, and most of those conio.h functions are inside other standard libraries. – Alberto Bonsanto Nov 21 '12 at 10:45
  • Here some useful references: (1) http://stackoverflow.com/questions/7226603/timeout-function (2) http://stackoverflow.com/questions/2917881/how-to-implement-a-timeout-in-read-function-call – Grijesh Chauhan Nov 21 '12 at 10:48
  • Standard C has nothing useful in this department. You need to use platform-specific APIs. [This](http://stackoverflow.com/questions/57615/how-to-add-a-timeout-to-console-readline) is a nice Windows-oriented discussion, it uses C# but it shouldn't be too hard to do the same in any language. – n. m. could be an AI Nov 21 '12 at 10:57
  • It would be useful to know what compiler are you using and on what platform (linux, win, ..) – German Garcia Nov 21 '12 at 19:10

3 Answers3

2

Use select() function to set a timeout for your scanf

The following code is an example of how use it.

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

int main(void)
{
    int x;
    fd_set          set;
    struct          timeval timeout = {0};

    FD_ZERO(&set);


   while(1)
   {
        timeout.tv_sec = 30;
        FD_SET(fileno( stdin ), &set);
        printf ("enter a number:");
        fflush (stdout);
        if (select(FD_SETSIZE, &set, NULL, NULL, &timeout))
        {

           scanf("%d", &x);
           printf("The number you put is %d\r\n",x);

        }
        else
        {
                printf("\r\nTimeout: Stop reading\r\n");
                break;
        }
    }
}
MOHAMED
  • 41,599
  • 58
  • 163
  • 268
  • Hi, I'm sorry I couldn't compile your code. I've gotten these errors: [Error] C:\Users\SilverRhythm\Documents\C-Free\Temp\Untitled5.cpp:8: error: `fd_set' was not declared in this scope [Error] C:\Users\SilverRhythm\Documents\C-Free\Temp\Untitled5.cpp:8: error: expected `;' before "set" [Error] C:\Users\SilverRhythm\Documents\C-Free\Temp\Untitled5.cpp:11: error: `set' was not declared in this scope [Error] C:\Users\SilverRhythm\Documents\C-Free\Temp\Untitled5.cpp:11: error: `FD_ZERO' was not declared in this scope – Jitzu Zu Nov 21 '12 at 15:16
  • and these as well : [Error] C:\Users\SilverRhythm\Documents\C-Free\Temp\Untitled5.cpp:17: error: `FD_SET' was not declared in this scope [Error] C:\Users\SilverRhythm\Documents\C-Free\Temp\Untitled5.cpp:20: error: `FD_SETSIZE' was not declared in this scope [Error] C:\Users\SilverRhythm\Documents\C-Free\Temp\Untitled5.cpp:20: error: `select' was not declared in this scope – Jitzu Zu Nov 21 '12 at 15:18
  • I'm new to 'fd_set', so I'm not sure to repair it. It's my first time using these functions. – Jitzu Zu Nov 21 '12 at 15:20
  • I build my source code on linux and it works. check in your source code that you include `#include #include #include ` – MOHAMED Nov 21 '12 at 17:14
  • are you using visual studio ? – MOHAMED Nov 21 '12 at 17:15
  • check if one of the followinf=g include could solve your problem maybe one of them contains select I did not check it `#include #include #include #include #include #include #include #include ` – MOHAMED Nov 21 '12 at 17:28
  • Awesome. I've got it. Thank you so much. – Jitzu Zu Nov 21 '12 at 20:09
1

Although the time_t structure returned by time() is most likely a number of seconds, you should not be performing maths on it. Instead use difftime()

double difftime ( time_t time2, time_t time1 );

Calculates the difference in seconds between time1 and time2.

You do not need to call main() from within main() and I'm not sure why you would think that is a good idea.

Also, getchar() will wait for a key to be pressed, so it won't be counting time in the background.

SpacedMonkey
  • 2,725
  • 1
  • 16
  • 17
0

This task is usually done using threads. In one thread getchar is called which blocks the thread execution, another thread does sleep() and then kills the first thread.

Another way to do this is to use non-blocking read() from the standard input using pselect (2), but it's more tricky and does not suit small applications well.

Though a solution with pthreads in unix-style is quite verbose:

#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <pthread.h>

struct read_int {
    int success;
    int value;
    struct timespec timeout;
};

void* read_thread(void *arg) {
    struct read_int *s = arg;
    printf("Enter a number: ");
    scanf("%d", &s->value);
    s->success = 1;
    return NULL;
}

#define CHECK_RET(ret, func) \
    if (ret) { fprintf(stderr, func"() == %d\n", ret); return ret; }

int main() {
    pthread_t rthr;
    pthread_attr_t thr_attr;

    struct read_int s = { 0 };
    int ret;

    ret = clock_gettime(CLOCK_REALTIME, &s.timeout);
    if (ret == -1) { fprintf(stderr, "clock_gettime() == %d\n", ret);  return ret; }

    s.timeout.tv_sec += 5;

    ret = pthread_attr_init(&thr_attr);
    CHECK_RET(ret, "pthread_attr_init");

    ret = pthread_create(&rthr, &thr_attr, read_thread, &s);
    CHECK_RET(ret, "pthread_create");

    ret = pthread_attr_destroy(&thr_attr);
    CHECK_RET(ret, "pthread_attr_destroy");

    pthread_timedjoin_np(rthr, NULL, &s.timeout);

    if (s.success) {
        printf("\ngot value %d\n", s.value);
    } else {
        pthread_cancel(rthr);
        printf("\nTimed out, exiting...\n\n");
    }
}
Dmytro Sirenko
  • 5,003
  • 21
  • 26