How to start counting 5 seconds before exiting from program? - c

I've been pulling my hair out on this for many hours now. Basically, I have a program that asks the user to enter his password (123), and if the user doesn't enter anything for 5 seconds then the program will exit (game over). I've been trying to use time(NULL) and clock() but still no luck. Can anyone point me in the right direction, please? Thanks a lot in advance!
Here's my code:
#include <stdio.h>
#include <time.h>
int main(){
int password = 0;
int num = 0;
printf("%s\n", "Please enter your password");
scanf("%d", &password);
// Here I need to check if user didnt enter anything for 5 seconds,
// and if he didnt enter anything then exit out of the program
// I tried using time
// time_t start = time(NULL);
// time_t stop = time(NULL);
// if(((stop - start) * 1000) > 5000){
// printf("%s\n", "Game Over");
// break;
// }
printf("%s\n", "Thank you for entering your password, now enter any number");
scanf("%d", &num);
return 0;
}

Your main challenge is that scanf() - as well as getchar() and similar commands - are blocking. An unknown interval of time could elapse before the user actually enters any input - and your five seconds might already be up at that stage.
select() - monitor file descriptors with timeout
I think one of the most feasible options is to use select() - which monitors for activity on certain sets of file descriptors. Specifically, you want to monitor for activity on the stdin file descriptor.
The following accomplishes something close to what you need I believe.
#include <stdio.h>
#include <sys/select.h>
#include <termios.h>
#include <time.h>
#include <unistd.h>
int main(void) {
char buf[16] = {'\0'};
char *pass = buf;
time_t time_update = 0, time_now = 0;
struct timeval tm;
int res = 0;
struct termios term_attr, new_attr;
fd_set rset;
// Change terminal attributes (We don't want line-buffered mode.)
tcgetattr(fileno(stdin), &term_attr);
tcgetattr(fileno(stdin), &new_attr);
new_attr.c_lflag &= ~(ICANON | ECHO);
tcsetattr(fileno(stdin), TCSANOW, &new_attr);
printf("Enter password: ");
time_update = time(NULL);
while (1) {
tm.tv_sec = 0;
tm.tv_usec = 50000;
FD_ZERO(&rset);
FD_SET(STDIN_FILENO, &rset);
res = select(fileno(stdin) + 1, &rset, NULL, NULL, &tm);
if (FD_ISSET(STDIN_FILENO, &rset)) {
time_update = time(NULL);
int c = getchar();
if (c == '\n') {
break;
}
*pass = c;
pass++;
}
time_now = time(NULL);
if (time_now - time_update >= 5) {
puts("Timed out ...");
break;
}
}
pass = buf;
printf("You entered: %s \n", pass);
// Restore original terminal attributes
tcsetattr(fileno(stdin), TCSANOW, &term_attr);
return 0;
}
Notes:
The last argument to select() is a struct timeval which specifies how long to wait for activity on the specified file descriptors. In this case I have specified a timeout of 50 milliseconds.
The terminal needs to be placed in character buffer mode rather than line-buffered mode. (Otherwise you will need to press enter every time there is a new character.)
Operating system support
select() is part of the POSIX specification, but I do not know if it is implemented on Windows. Maybe someone can clarify?
Also ... I do not know if setting the terminal attributes will work as expected on Windows either. (I have only tested on Linux.)
I realize this solution might be a little longer / more complex than you hoped - but I am not aware of an easier way.

Related

How to: call a method every second impleting getchar() or if it's empty then continue

So I'm trying to do something like this: I have a function calling another one in which I am reading text line by line from a given file and I want it to execute what it reads(working atm), BUT it should only execute a line once every second so the user has time to write for example an S in stdin, meaning STOP (or something like that), else if the users didn't input anything then the program should continue to iterate the file. How can I do this ?
What I have been using to try this is signal and alarms(), testing out something like this:
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
#include<string.h>
volatile int breakflag = 2;
void handle(int sig){
if( getchar()=='a' ){
printf("it read something from input\n");
--breakflag;
}else{
printf("it didn't read anything from input\n");
--breakflag;
}
alarm(2);
}
int main(){
/*let's say this is part of the method that i call each iteration until I've read EOF.
now is the part that i should execute whatever i get into the stdin,
or if it's empty it should continue to next iteration...
*/
signal(SIGALRM, handle);
alarm(1);
while(breakflag){
sleep(1);
}
printf("done\n");
return 0;
}
Sorry for the long description. But I'm having a hard time trying to get anything that works out.
I have found a few answers that helped me throughout this problem but i can't seem to figure it out the way i need it....
You can use select with a timeout of 1 sec, for instance :
#include <stdio.h>
#include <sys/select.h>
int main()
{
struct timeval tv;
fd_set fd;
int i;
FD_ZERO(&fd);
for (i = 0; i != 10; ++i) {
FD_SET(0, &fd);
tv.tv_sec = 1;
tv.tv_usec = 0;
if (select(0 + 1, &fd, NULL, NULL, &tv) == -1) {
perror("error on select");
break;
}
if (FD_ISSET(0, &fd)) {
int c = getchar();
if (c == EOF) {
puts("EOF");
break;
}
printf("read char '%c'\n", c);
}
else
puts("nothing to read");
}
return 0;
}
Compilation and execution (under Linux) :
pi#raspberrypi:/tmp $ gcc -Wall c.c
pi#raspberrypi:/tmp $ (sleep 2 ; echo -n a ; sleep 3 ; echo -n z) | ./a.out
nothing to read
nothing to read
read char 'a'
nothing to read
nothing to read
nothing to read
read char 'z'
EOF
pi#raspberrypi:/tmp $ ./a.out

Display something every x seconds with different output

I want to output the ASCII Code of the last key I pressed, every x second.
As example:
If i press a(97), the terminal should show the 97 every x second. When I now press the w(119), the program now should print the 119 instead of the 97.
So far my program just prints the first key I've pressed.
Here are the main and the other method:
int main(int argc, char const *argv[]){
printf("Hello World!");
while(1){
movePlayer();
fflush(stdout);
sleep(1);
}
return 0;
}
void movePlayer(){
system("/bin/stty raw");
int input = getchar(); //support_readkey(1000);
//fprintf(stdout, "\033[2J");
//fprintf(stdout, "\033[1;1H");
printf("\b%d",input);
system("/bin/stty cooked");
}
EDIT:
With a little bit of testing i've now a method which solves my problem
int read_the_key(int timeout_ms) {
struct timeval tv = { 0L, timeout_ms * 1000L };
fd_set fds;
FD_ZERO(&fds);
FD_SET(0, &fds);
int r = select(1, &fds, NULL, NULL, &tv);
if (!r) return 0;
return getchar();
}
getchar() waits for only one character, so this:
while(1){
movePlayer(); // getchar() and printf() here
fflush(stdout);
sleep(1);
}
causes this behavior. You read one character, you print it in movePlayer(). Then you flush the output buffer and go to sleep. Then you just repeat, which means that you have to input again.
Store the input and print it again, if you wish. However, your function will always wait for new input to arrive.
Here is an attempt with read() as suggested, but it will have similar behavior to your code as it is now:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int old_c = -1;
char c[1] = {0};
void movePlayer();
int main(int argc, char const *argv[]){
while(1) {
movePlayer();
fflush(stdout);
sleep(1);
}
return 0;
}
void movePlayer(){
system("/bin/stty raw");
if(read(STDIN_FILENO, c, sizeof(c)) > 0)
old_c = (int)c[0];
if(old_c == -1)
old_c = (int)c[0];
printf("\b%d", old_c);
system("/bin/stty cooked");
}
Please read read() from stdin to go on. You can tell read() for how many characters to wait and then return, but how will you know if the user intends to input a new character to command read() to wait for user's input?
As a result, I would say that you can not do what you wish, at least as far as I can tell, with a simple approach. You could have your program feed the stale input to stdin, so that your program has the impression it reads user's input. However, in case the user actually inputs fresh input, your program should handle that case carefully.
You can setup SIGALARM handler, setup alarm after x seconds and display what getchar returns in handler

How can I prevent scanf() to wait forever for an input character?

I want to fulfill the following things in a console application:
If user inputs a character, the application will do the
corresponding task. For example, if user inputs 1, the program
will do task 1, if user inputs q, the program will quit;
If user inputs nothing, the program will do the default task every 10 seconds (the time needn't to be very strict).
Here is my code:
#include <stdio.h>
#include <time.h>
char buff[64];
char command;
while(command != 'q')
{
begin:
printf(">> ");
scanf("%s", buff);
command = buff[0];
switch (command)
{
case '1':
// task 1 code will be added here;
break;
case '2':
// task 2 code will be added here;
break;
case 'q':
printf("quit the loop.\n");
break;
}
// wait for 10 seconds;
Sleep(10000);
// default task code will be added here;
if(command != 'q')
{
goto begin;
}
}
But the problem is the program will trap at the line of scanf() function forever to wait for an input character, if no character is entered. So I'm wondering how to skip the line of scanf() after a certain time, I mean for example, if no input after 1 second, the program can continue, so as to fulfill the second thing listed above.
The platform is Windows, if it matters.
I've removed the semicolon after the while() it was an obvious mistake.
Try using the select() function. Then you can wait for 10 seconds until you can read from stdin without blocking. If select() returns with zero, perform the default action.
I don't know if this works on windows, it's POSIX standard. If you happen to develop on unix/linux, try man select
I just wrote a working example using select:
#include <stdlib.h>
#include <stdio.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define MAXBYTES 80
int main(int argc, char *argv[])
{
fd_set readfds;
int num_readable;
struct timeval tv;
int num_bytes;
char buf[MAXBYTES];
int fd_stdin;
fd_stdin = fileno(stdin);
while(1) {
FD_ZERO(&readfds);
FD_SET(fileno(stdin), &readfds);
tv.tv_sec = 10;
tv.tv_usec = 0;
printf("Enter command: ");
fflush(stdout);
num_readable = select(fd_stdin + 1, &readfds, NULL, NULL, &tv);
if (num_readable == -1) {
fprintf(stderr, "\nError in select : %s\n", strerror(errno));
exit(1);
}
if (num_readable == 0) {
printf("\nPerforming default action after 10 seconds\n");
break; /* since I don't want to test forever */
} else {
num_bytes = read(fd_stdin, buf, MAXBYTES);
if (num_bytes < 0) {
fprintf(stderr, "\nError on read : %s\n", strerror(errno));
exit(1);
}
/* process command, maybe by sscanf */
printf("\nRead %d bytes\n", num_bytes);
break; /* to terminate loop, since I don't process anything */
}
}
return 0;
}
Note: the poll() example below is OK too, no problem. For the rest I chose to read the available bytes into a buffer (up to MAXBYTES). It can be (s)scanned afterwards. (scanf() just isn't too much my friend, but that's a personal taste matter).
Here is a working example of how to do this with poll (probably the most 'correct' way on Linux):
#include <unistd.h>
#include <poll.h>
#include <stdio.h>
int main()
{
struct pollfd mypoll = { STDIN_FILENO, POLLIN|POLLPRI };
char string[10];
if( poll(&mypoll, 1, 2000) )
{
scanf("%9s", string);
printf("Read string - %s\n", string);
}
else
{
puts("Read nothing");
}
return 0;
}
The timeout is the third argument to poll and is in milliseconds - this example will wait for 2 seconds for input on stdin. Windows has WSAPoll, which should work similarly.
But the problem is the program will trap at the line of scanf() function forever to wait for an input character,
Remove the semicolon after while.
Try alarm(3)
#include <stdio.h>
#include <unistd.h>
int main(void)
{
char buf [10];
alarm(3);
scanf("%s", buf);
return 0;
}
As others have said, the best way to do truly async IO is with select(...).
But a quick and dirty way to do what you want is with getline(...) which will return the number of bytes read every time (not hanging on IO) and returns -1 on no bytes read.
The following is from the getline(3) man page:
// The following code fragment reads lines from a file and writes them to standard output.
// The fwrite() function is used in case the line contains embedded NUL characters.
char *line = NULL;
size_t linecap = 0;
ssize_t linelen;
while ((linelen = getline(&line, &linecap, fp)) > 0)
fwrite(line, linelen, 1, stdout);
Unfortunately, what you are asking for is not possible in plain ISO C. However, most platforms offer platform-specific extensions which provide the functionality that you require.
Since you stated that your question applies to Microsoft Windows, the two functions that you are looking for are WaitForSingleObject and ReadConsoleInput. You won't be able to use the function scanf or C-style streams (FILE*) for this.
The function WaitForSingleObject allows you to wait until a specific object is in a signalled state. It also allows you to set a timeout (which should be 10 seconds in your case).
One type of object that WaitForSingleObject can wait for is a console handle. It will be in a signalled state when there is new input available to be read by ReadConsoleInput. According to my tests, it won't work reliably with ReadConsole though, because even if WaitForSingleObject indicates that input is waiting, the function ReadConsole will still sometimes block. This is because in contrast to ReadConsoleInput, the function ReadConsole will filter some events. Therefore, attempting to read one event with ReadConsole may actually attempt to read more than one raw event, which will cause the function to block if there are no non-filtered raw events available. The function ReadConsoleInput does not have this problem, as it works with raw events directly and does not filter any.
Here is my program which uses the functions mentioned above, and does exactly what you asked for.
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
void DoDefaultTask()
{
printf( "Doing default task.\n" );
}
void DoTask1()
{
printf( "Doing task #1.\n" );
}
void DoTask2()
{
printf( "Doing task #2.\n" );
}
int main(void)
{
INPUT_RECORD ir;
HANDLE hConInput = GetStdHandle(STD_INPUT_HANDLE);
DWORD dwReadCount;
bool should_prompt = true, quit = false;
while ( !quit )
{
//prompt user for input
if ( should_prompt )
{
printf( "Please select an option: " );
should_prompt = false;
}
//flush output
fflush( stdout );
switch ( WaitForSingleObject( hConInput, 10000 ) )
{
case WAIT_OBJECT_0:
//attempt to read input
if ( !ReadConsoleInput( hConInput, &ir, 1, &dwReadCount ) || dwReadCount != 1 )
{
fprintf( stderr, "Unexpected input error!\n" );
exit( EXIT_FAILURE );
}
//only handle key-down events
if ( ir.EventType != KEY_EVENT || !ir.Event.KeyEvent.bKeyDown )
break;
//echo output, if character is printable
if ( isprint( (unsigned char)ir.Event.KeyEvent.uChar.AsciiChar ) )
{
printf( "%c", ir.Event.KeyEvent.uChar.AsciiChar );
}
printf( "\n" );
switch ( ir.Event.KeyEvent.uChar.AsciiChar )
{
case '1':
DoTask1();
break;
case '2':
DoTask2();
break;
case 'q':
printf( "Quitting program...\n" );
quit = true;
break;
default:
printf( "Unknown command.\n" );
}
should_prompt = true;
break;
case WAIT_TIMEOUT:
printf( "Timeout!\n" );
DoDefaultTask();
should_prompt = true;
break;
default:
fprintf( stderr, "unexpected error!" );
exit( EXIT_FAILURE );
}
}
return 0;
}
This program has the following behavior:
Please select an option: 1
Doing task #1.
Please select an option: 2
Doing task #2.
Please select an option: 3
Unknown command.
Please select an option: 4
Unknown command.
Please select an option: Timeout!
Doing default task.
Please select an option: Timeout!
Doing default task.
Please select an option: 1
Doing task #1.
Please select an option: 3
Unknown command.
Please select an option: 2
Doing task #2.
Please select an option: 1
Doing task #1.
Please select an option: Timeout!
Doing default task.
Please select an option: q
Quitting program...

How to loop select() to poll for data ad infinitum

#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
int main ()
{
char name[20];
fd_set input_set;
struct timeval timeout;
int ready_for_reading = 0;
int read_bytes = 0;
/* Empty the FD Set */
FD_ZERO(&input_set );
/* Listen to the input descriptor */
FD_SET(0, &input_set);
/* Waiting for some seconds */
timeout.tv_sec = 10; // 10 seconds
timeout.tv_usec = 0; // 0 milliseconds
/* Invitation for the user to write something */
printf("Enter Username: (in 15 seconds)\n");
printf("Time start now!!!\n");
/* Listening for input stream for any activity */
ready_for_reading = select(1, &input_set, NULL, NULL, &timeout);
/* Here, first parameter is value of the socket descriptor + 1 (STDIN descriptor is 0, so
* 0 +1 = 1)
* in the set, second is our FD set for reading,
* third is the FD set in which any write activity needs to updated, which is not required
* in this case. Fourth is timeout
*/
if (ready_for_reading == -1) {
/* Some error has occured in input */
printf("Unable to read your input\n");
return -1;
} else {
if (ready_for_reading) {
read_bytes = read(0, name, 19);
printf("Read, %d bytes from input : %s \n", read_bytes, name);
} else {
printf(" 10 Seconds are over - no data input \n");
}
}
return 0;
}
How to do the same, but not just once, but in infinite loop which breaks after encountering 'quit' string (for example). Every way I tried - failed.
So if no data has been inputed after 10 seconds program just prints "10 secs are over - no data input" and then starts waiting again. Same after input - just begins again and behave the same every time in infinite loop.
Am little desperate already, please - help.
Thanks.
I don't really see the problem here. Basically just put everything you want in the loop, and let it run. Did you try this?
int main ()
{
/* Declarations and stuff */
/* ... */
/* The loop */
int break_condition = 0;
while (!break_condition)
{
/* Selection */
FD_ZERO(&input_set ); /* Empty the FD Set */
FD_SET(0, &input_set); /* Listen to the input descriptor */
ready_for_reading = select(1, &input_set, NULL, NULL, &timeout);
/* Selection handling */
if (ready_for_reading)
{
/* Do something clever with the input */
}
else
{
/* Handle the error */
}
/* Test the breaking condition */
break_condition = some_calculation();
}
return 0;
}
Note that you have to have keep resetting the selection inside the loop so that it will respond again in the next iteration.
The select() function can be told to block indefinitely by setting timeout to NULL. See select(2) man page:
timeout is an upper bound on the amount of time elapsed before select() returns. If both fields of the timeval stucture are zero, then select() returns immediately. (This is useful for polling.) If timeout is NULL (no timeout), select() can block indefinitely.
So what you want is:
...
ready_for_reading = select(1, &input_set, NULL, NULL, NULL);
...

Timeout Function

I want to make a code in which Name of User will be asked to input, but in a time limit of 15 seconds. If user cross the limit & failed to input a name(or any string), then code will be terminated & "Time Out" Massage will be display otherwise Name should be saved & "Thanks" massage will be display. I had try like this but it's wrong & not working. Please give me a solution for this.. Thanks.
#include <stdio.h>
#include <time.h>
int timeout ( int seconds )
{
clock_t endwait;
endwait = clock () + seconds * CLOCKS_PER_SEC ;
while (clock() < endwait) {}
return 1;
}
int main ()
{
char name[20];
printf("Enter Username: (in 15 seconds)\n");
printf("Time start now!!!\n");
scanf("%s",name);
if( timeout(5) == 1 ){
printf("Time Out\n");
return 0;
}
printf("Thnaks\n");
return 0;
}
Probably this dummy program might help you:
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#define WAIT 3
int main ()
{
char name[20] = {0}; // in case of single character input
fd_set input_set;
struct timeval timeout;
int ready_for_reading = 0;
int read_bytes = 0;
/* Empty the FD Set */
FD_ZERO(&input_set );
/* Listen to the input descriptor */
FD_SET(STDIN_FILENO, &input_set);
/* Waiting for some seconds */
timeout.tv_sec = WAIT; // WAIT seconds
timeout.tv_usec = 0; // 0 milliseconds
/* Invitation for the user to write something */
printf("Enter Username: (in %d seconds)\n", WAIT);
printf("Time start now!!!\n");
/* Listening for input stream for any activity */
ready_for_reading = select(1, &input_set, NULL, NULL, &timeout);
/* Here, first parameter is number of FDs in the set,
* second is our FD set for reading,
* third is the FD set in which any write activity needs to updated,
* which is not required in this case.
* Fourth is timeout
*/
if (ready_for_reading == -1) {
/* Some error has occured in input */
printf("Unable to read your input\n");
return -1;
}
if (ready_for_reading) {
read_bytes = read(0, name, 19);
if(name[read_bytes-1]=='\n'){
--read_bytes;
name[read_bytes]='\0';
}
if(read_bytes==0){
printf("You just hit enter\n");
} else {
printf("Read, %d bytes from input : %s \n", read_bytes, name);
}
} else {
printf(" %d Seconds are over - no data input \n", WAIT);
}
return 0;
}
Update:
This is now tested code.
Also, I have taken hints from man for select. This manual already contains a code snippet which is being used to read from the terminal and timeout in 5 seconds in case of no activity.
Just a brief explanation in case the code is not well written enough:
We add the input stream (fd = 1) to the FD set.
We initiate select call to listen to this FD set created for
any activity.
In case any activity occurs within the timeout period, that is
read through the read call.
In case there was no activity, timeout occurs.
Hope this helps.
scanf() is not the best function to get an input in a limited time frame.
Instead I would build a specific input function around select() (for managing timeout) and read() (for getting input) system calls.
One thing you have to think about, is that you have a single thread of execution in your program. As such, the timeout function will only be called when the scanf function will be terminated. This is not what you want.
One way to do this task, is to use the select function. It waits for a potentially limited amount of time (your timeout) for availability of input on some file descriptors (stdin for you).

Resources