How to use scanf without stopping the program C language? - c

I'm doing a counter where I'm showing how many seconds the user has to make the input. The problem is that when I use scanf(), the program will stop and will wait for the answer, but I don't want that. I'd like to keep running the counter even thought the user doesn't put anything.
Example:
for(int i=10;i>=0;i--){
i==0? printf("time over\n"):printf("%d seconds left\n",i);
scanf("%s", decision);
sleep(1);
}
What can i do to solve this?

Like mentioned in the comments one possibility would be to use poll.
man poll says:
poll() examines a set of file descriptors to see if some of them are
ready for I/O or if certain events have occurred on them.
In code it could look like this:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/poll.h>
#include <stdbool.h>
int main() {
struct pollfd fds[1];
fds[0].fd = STDIN_FILENO;
fds[0].events = POLLIN;
bool dataAvailable = false;
for (int i = 10; i >= 0 && !dataAvailable; i--) {
switch (poll(fds, 1, 1000)) {
case -1:
perror("poll failed");
exit(1);
case 0:
printf("%d seconds left\n", i);
break;
default:
dataAvailable = true;
}
}
if (dataAvailable) {
//read from stdin
} else {
fprintf(stderr, "no input\n");
exit(1);
}
return 0;
}

Related

Why simple read string from non blocking IO in C behaves oddly in loop?

I have just encountered a problem which I couldn't found the reason. The code works as Below:
There is a while loop which does a lot of stuff in the middle (Does not even written), and has a non-blocking IO to receive the end process command (which is a string).
At any time, a user could come and wants to finish the process. He/She would press some keys and then press the [Enter] button.
After select find out there is an input, it uses the input string and evaluates with the EXIT string and end the process.
Now the problem is when I use the exitFlag string as the termination key it just don't accept it and keeps writing <the printf() statement> until i hit cntrl+c.
I have tried scanf(), fputs(), fread() to recieve input string from stdin and also used fflush(stdin) and fflush(stdout) to clear the std buffers.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
fd_set s;
struct timeval timeout;
timeout.tv_sec = 3;
timeout.tv_usec = 0;
char exitFlag[10];
int sFlag;
printf("Enter \"EXIT\" to End the Process\n");
while (1)
{
fflush(stdin); fflush(stdout);
FD_ZERO(&s);
FD_SET(STDIN_FILENO, &s);
timeout.tv_sec = 3; timeout.tv_usec = 0;
sFlag = select(STDIN_FILENO+1, &s, NULL, NULL, &timeout);
printf("%d: ", sFlag);
if (sFlag < 0) _exit(0);
else if (sFlag == 0)
{
printf("-\n");
fflush(stdin); fflush(stdout);
}
else
{
fflush(stdin); fflush(stdout);
scanf("%[^\n]s", &exitFlag); // fgets( exitFlag, 10, stdin); // fread( exitFlag, 10, 1 ,stdin);
printf("You have Pressed %s, Enter \"EXIT\" to End the Process: ", exitFlag);
printf("%s\n", exitFlag);
if ( memcmp(&exitFlag, "EXIT", 4) == 0 ) break;
}
}
return 0;
}
Ironically, I don't encounter similar problem when using char as the termination key input rather than string.
I would be very thankful if someone explains where I made mistake in the IO or any other place.
I have also reviewed prior questions carefully but they had seemed to work with a single keyboard press which was not safe for common use!
include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
fd_set s;
struct timeval timeout;
timeout.tv_sec = 3;
timeout.tv_usec = 0;
char exitFlag;
int sFlag;
while (1)
{
fflush(stdout);
FD_ZERO(&s);
FD_SET(STDIN_FILENO, &s);
timeout.tv_sec = 3; timeout.tv_usec = 0;
sFlag = select(STDIN_FILENO+1, &s, NULL, NULL, &timeout);
if (sFlag < 0) _exit(0);
else if (sFlag == 0)
{
fflush(stdout);
printf("-\n");
}
else
{
fflush(stdin);
scanf("%c", &exitFlag);
printf("You have Pressed %c, Press E to exit: ", exitFlag);
printf("%c\n", exitFlag);
fflush(stdout);
if ( exitFlag =='E' ) break;
}
}
return 0;
}

C- Program won't terminate after 30 seconds

We were asked to prompt the user to enter phrases, and continue asking them until they get the correct phrase needed, for 30 seconds. Here's what I've come up with:
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void childprocess(void)
{
int start = 30;
do
{
start--;
sleep(1);
} while (start >= 0);
printf("Time ran out!\n");
exit(EXIT_SUCCESS);
}
int main(void)
{
pid_tiChildID;/* Holds PID of current child */
char word[100] = "cat";
char input[100];
int length;
iChildID = fork();
if (0 > iChildID)
{
perror(NULL);
return 1;
}
else if (0 == iChildID)
{
childprocess();
return 0;
}
/* Parent process */
while (1)
{
fgets(input, sizeof(input), stdin);
length = strlen(input);
if (input[length - 1] == '\n')
{
--length;
input[length] = '\0';
}
if (strcmp(word, input) == 0)
break;
printf("Try again\n");
}
kill(iChildID, SIGUSR1);/* terminate repeating message */
printf("Finally!\n");
return 0;
}
The problem: after 30 seconds, it prints "Time runs out" but won't terminate. How do I terminate the program after 30 seconds? Any help?
Here, you are using fork which creates two separate processes with two different PIDs. You are killing child process but parent is still running so program just dont quit.
You could have also used pthread instead of fork with remains in same single process but what ever you are trying to achieve is simple with alarm function. You dont have to manage any other process. Just use alarm.
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static void ALARMhandler(int sig)
{
printf("Time ran out!\n");
exit(EXIT_SUCCESS);
}
int main(void)
{
char word[100] = "cat";
char input[100];
size_t length;
signal(SIGALRM, ALARMhandler);
alarm(30);
while(1) {
fgets(input, sizeof(input),stdin);
length = strlen(input);
if(input[length-1] == '\n') {
--length;
input[length] = '\0';
}
if (strcmp(word,input) == 0)
break;
printf("Try again\n");
}
/* terminate repeating message */
printf("Finally!\n");
return 0;
}
Hope it helps !!

Wait only 5 second for user input

I want to write a simple c program in turbo c++ 4.5 editor such that in only wait 5 seconds for user input. As an example,
#include <stdio.h>
void main()
{
int value = 0;
printf("Enter a non-zero number: ");
// wait only 5 seconds for user input
scanf("%d",&value);
if(value != 0) {
printf("User input a number");
} else {
printf("User dont give input");
}
}
So, what will be the code for 5 seconds wait for 'scanf' functionality and otherwise execute if-else part.
Try a select(2) loop: https://www.mirbsd.org/man2/select on stdin (fd#0) with a timeout of 5 seconds; run the scanf(3) only if select returns indicating there is data. (See the c_read() function in the mksh source code for an example.)
Other functions, like poll(2), are also possible. Nonblocking I/O is a bit overkill.
OK, here’s a working (on MirBSD) example using select:
#include <sys/types.h>
#include <sys/time.h>
#include <err.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int
main(void)
{
int value = 0;
struct timeval tmo;
fd_set readfds;
printf("Enter a non-zero number: ");
fflush(stdout);
/* wait only 5 seconds for user input */
FD_ZERO(&readfds);
FD_SET(0, &readfds);
tmo.tv_sec = 5;
tmo.tv_usec = 0;
switch (select(1, &readfds, NULL, NULL, &tmo)) {
case -1:
err(1, "select");
break;
case 0:
printf("User dont give input");
return (1);
}
scanf("%d", &value);
if (value != 0) {
printf("User input a number");
} else {
printf("User dont give input");
}
return (0);
}
You might want to play with the exit codes a bit and sprinkle a few \n throughout the code. The fflush(stdout); is important so that the prompt is shown in the first place…
#include <stdio.h>
#include <signal.h>
void handler(int signo)
{
return;
}
int main()
{
int x;
struct sigaction sa;
sa.sa_handler = handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGALRM, &sa, NULL);
alarm(5);
if (scanf("%d", &x) == 1)
{
printf("%d\n", x);
alarm(0); // cancel the alarm
}
else
{
printf("timedout\n");
}
return 0;
}
well you can use the halfdelay() function from the curses library

Stop some commands used in the system() function

I have a problem with system() function.
I need to implement a simple bash, one of the modules of the my project is to permit user types some bash command to execute it.
Above what i'm doing actually:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// similar to gets
int reads(char* str)
{
#ifndef WIN32
fflush(stdout);
strcpy(str,GetServiceLine());
#else
gets(str);
#endif
return 1;
}
int main(void) {
char str[100];
while(strcmp(str, "exit")) {
printf("\nNote: type \"exit\" to return menu\n");
printf("MyBash$ ");
reads(str);
system(str);
}
return 0;
}
My problem is with commands like ping.
When i run this code on my PC and i try execute ping command for a legal IP it works fine, i can stop the ping process using CTRL+C, but when i run it on my target on the same way i can't use CTRL+C and my process keep always at system() call.
Does somebody can help me?
Note: i read this post about how to use CTRL+C to break a system function. I tried the suggestion but didn't work.
Thanks.
Since you hadn't tried it yet I'll throw it up here as a suggestion. You can always install a signal handler to catch signals that you are interested in.
Here's a quick example using (mostly) your code which demonstrates how it's done:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void intHandler(int dummy)
{
exit(1); // Do whatever you want here to handle it...
}
int main(void)
{
char str[100];
signal(SIGINT, intHandler);
signal(SIGKILL, intHandler);
while(strcmp(str, "exit")) {
printf("\nNote: type \"exit\" to return menu\n");
printf("MyBash$ ");
gets(str);
system(str);
}
return 0;
}
I can catch a ctrl+C using this, but I'm not sure if it's what you're looking for.
After the comments above i just thought of explaining why exactly you can't control this in a graceful manner (some hacks are suggested in comments though).
system command is going to behave exactly if you forked a child process and then called exec on the child for executing the binary passed to exec as an argument.
The system() function shall ignore the SIGINT and SIGQUIT signals, and shall block the SIGCHLD signal, while waiting for the command to terminate. If this might cause the application to miss a signal that would have killed it, then the application should examine the return value from system() and take whatever action is appropriate.
Remember, this is very much OS specific behavior and there is no standard as such.
system() function call in Linux
Internally ping utility would run on icmp and waits until a response is received from the other node.
You might write a signal handler as suggested in another answer and call a killpid() but it would be blocked until the call to system() returns. This is stated in the specs of the function. So you might be able to terminate but only AFTER the call has returned. :)
Below the code used to fix my problem. I don't know if is the better solution, but solved my problem in this case.
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// similar to gets
int reads(char* str)
{
#ifndef WIN32
fflush(stdout);
strcpy(str,GetServiceLine());
#else
gets(str);
#endif
return 1;
}
void getCommandName(char input[], char output[])
{
int count=0;
while (input[count] != NULL && input[count] != ' ' && input[count] != '\0') {
output[count] = input[count];
count++;
}
}
int killLastCommand(int pid)
{
char commandKill[30];
memset(commandKill, 0, 30);
sprintf(commandKill, "kill -9 %d", pid);
return(!system(commandKill));
}
int main(void) {
FILE *fp; //Will be used with popen()
char str[100];
char lastCommandName[50];
char pidofCommand[50];
char strLastPIDCommand[10];
int lastPIDCommand=0;
memset (str, 0, 100);
while(strcmp(str, "exit")) {
if (lastPIDCommand == 0) {
memset (lastCommandName, 0, 50); //Clean lastCommandName array
memset (pidofCommand, 0, 50); //Clean pidofCommand array
memset (strLastPIDCommand, 0, 10); //Clean strLastPIDCommand array
printf("\n\nNote: type \"exit\" to return menu\n");
printf("MyBash$ ");
reads(str);
if (strcmp(str, "exit")) {
sprintf(str, "%s &", str);
}
getCommandName(str, lastCommandName);
system(str);
sleep(1); //Sleep to guarantee than command will end
sprintf(pidofCommand, "pidof %s", lastCommandName);
//Saving PID
fp = popen(pidofCommand, "r");
if (fp) {
fgets(strLastPIDCommand, 10, fp);
lastPIDCommand = atoi(strLastPIDCommand);
} else {
//Handle error
}
pclose(fp);
printf("commandName = %s\r\n", lastCommandName);
printf("pid = %d\r\n", lastPIDCommand);
} else {
printf("\n\nYou have a command running, press 'kill' to stop it before to type another command\n");
printf("EITVBash$ \n\n");
reads(str);
// if (str[0] == 0x03) { //CTRL+C hexa code
if (!strcmp(str, "kill")) {
if (killLastCommand(lastPIDCommand)) {
lastPIDCommand = 0;
}
}
}
}
return 0;
}
My implementation probably isn't clean, but i don't have much experience with c.
Thanks everybody.

Stop only if some key is pressed in C

If I had a while loop that I wanted to stop only if the q key is pressed how would I do that.
However, I do NOT want it to quite the program
#define TRUE 1
#define FALSE 0
typedef int boolean;
int main(int argc,char* argv[]){
char *script = malloc(MAXPATH);
script = "ls";
boolean a;
a = TRUE;
while(a){ //this is the while loop i want to break incase of a keypress
system(script);
}
do something else
something else....
This will be running on Mac OS X.
both getchar() and getc() pause for a response which makes loop stop
you can use select() mechanism in UNIX-LIKE OS.
all in one function:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/select.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
fd_set readfds;
struct timeval tv;
int ch;
int bool, ret;
FD_ZERO(&readfds);
bool = 1;
while (bool) {
FD_SET(STDIN_FILENO, &readfds);
tv.tv_sec = 0;
tv.tv_usec = 0;
/* int select(int nfds, fd_set *readfds, fd_set *writefds,
* fd_set *exceptfds, struct timeval *timeout); */
ret = select(STDIN_FILENO + 1, &readfds, NULL, NULL, &tv);
if (ret < 0) {
perror("select error");
exit(1);
} else if (ret == 0) {
/* timeout */
} else if (FD_ISSET(STDIN_FILENO, &readfds)) {
ch = fgetc(stdin);
if (ch == 'q') {
bool = 0;
}
}
sleep(1);
fprintf(stderr, ".");
}
return 0;
}
native functions in C with which i can detect a keypress are :
getchar() and getc()
kbhit() is a function returns integer value whenever the key is pressed
you can use the above functions
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <time.h>
int main()
{
int m;
clrscr();
do
{
if(kbhit())
{
if((m=getch())==97)
{
printf("Key a is pressed....\n");
}
}
} while(1);
getch();
return 0;
}
I'm glad of alexchandel's answer. I had never heard of poll()
poll() is a good answer for POSIX style systems like the questioner's platform
_kbhit() is the simplest answer on MS Windows. Their Poll() is different of course
The 1 means just one descriptor block in my list, the 100 is milliseconds timout
my file handle is { 0, for stdin
read the man page for the many events you can interrogate, I only wanted POLLIN
#include <stdio.h>
#include <poll.h>
#include <errno.h>
static struct pollfd attention = { 0, POLLIN } ;
int main()
{
int x, y;
for (;;)
{
x = poll(&attention, 1, 100);
if (x < 0)
{
printf("problem %d\n", errno);
break;
}
else if (x)
{
printf("you rang %x ?", x);
y = getc(stdin);
printf(" %c of course\n", y);
if (y == '.') break;
}
}
return 0;
}
You could make the computation run in a pthread while the main loop reads char on stdin. SDL library has better input controls if you don't just want to read char from stdin. gtk also has events that the window receives. The command "xev" is a xlib program for linux that works similarly. It opens a blank window and it reads key events as they come.

Resources