1

I Have written a Fibonacci Series in C. It functions well and provide numbers more than 3e100 also.

But my question here, is, what is the user want to stop the print process in the middle and exit the loop, how to capture the users input ?

For instance, if he input that he wants first 100 numbers of the series, then changed mind and wants to exit the printing process, while its in the middle. How to do that ?

I Thought of capturing ^c (CTRL+C) when the loop runs, but I'm unsure how to do that.

Here is my code:

printf("Welcome to Fibonacci Series Mode.\n\nEnter how many numbers do you want from the series, from the start: ");
scanf("%d", &N);
x = 0;
y = 1;
F = 3;
Numbering = 3;
printf("Here is Your Series:\n\n");
if (N == 1)
{
    printf("[1] 0\n");
    Sleep(1000);
}
if (N == 2)
{
    printf("[1] 0\n");
    Sleep(75);
    printf("[2] 1\n");
    Sleep(1075);
}
if (N == 3)
{
    printf("[1] 0\n");
    Sleep(75);
    printf("[2] 1\n");
    Sleep(75);
    printf("[3] 1\n");
    Sleep(1075);
}
if (N > 3)
{
    printf("[1] 0\n");
    Sleep(75);
    printf("[2] 1\n");
    Sleep(75);
}
while (N > 3 && F <= N)
{
    xy = x + y;
    printf("[%.0d] %.5g\n", Numbering, xy);
    Sleep(75);
    x = y;
    y = xy;
    F++;
    Numbering++;
}
Sleep(1000);
}

That is just a portion of my whole code, which I am not including here, that's why you cannot see main() and the header files.

Littm
  • 4,923
  • 4
  • 30
  • 38
UnfreeHeX
  • 83
  • 1
  • 9
  • Is there an illegal value, such as `-1`? – Fiddling Bits Jun 14 '20 at 05:03
  • @FiddlingBits I dont think so. cause its all positive integers – UnfreeHeX Jun 14 '20 at 05:04
  • 1
    Does this answer your question? [Ctrl + C interrupt event handling in Linux](https://stackoverflow.com/questions/17766550/ctrl-c-interrupt-event-handling-in-linux) – kaylum Jun 14 '20 at 05:04
  • You can use a negative value as a indication the user wants to end the program. – Fiddling Bits Jun 14 '20 at 05:06
  • Use interrupted or kill signal – Shubham Srivastava Jun 14 '20 at 05:06
  • 1
    @FiddlingBits I understand the portion of negativity, but how am i able to catch a negative number while the loop runs? – UnfreeHeX Jun 14 '20 at 05:12
  • 1
    I don't see a problem: Ctrl-C will interrupt your program without you doing anything special. So I'm not sure whether you even tried what you wish: you might be surprised that it already works. Ctrl-C will end the program immediately, and then the user can re-run it with different inputs. If you want some other behavior, you'd have to state what you wish in plain English. – Kuba hasn't forgotten Monica Jun 14 '20 at 06:52
  • If you are writing a program for Windows, you can use `kbhit()` from `conio.h` to determine if a key has been hit, and `getch()` to read the key, but this is not part of the standard library and therefore not portable. – Erich Kitzmueller Jun 14 '20 at 07:36
  • @ErichKitzmueller Thank you sir. It worked for the loop, to ask for response, exit, and to continue with the loop. But i didn't use `getch()` for that process. i used `scanf()` i have only learned that till now. But may i know what is the difference though? – UnfreeHeX Jun 14 '20 at 08:27
  • `getch()` reads a character, unbuffered, without echoing it. See also https://stackoverflow.com/questions/34474627/linux-equivalent-for-conio-h-getch to learn how to replace it in Non-Windows environments. – Erich Kitzmueller Jun 14 '20 at 15:05

1 Answers1

3

In C, IO is blocking by default. So if you want to listen to user input during the loop, you must wait for the user's input before moving on.

The solution to this is using signals. Specifically SIGINT with CTRL + C. Now it is possible to catch this signal on your program side to do some cleanup or just anything else you want. Your concern might be to make a function for graceful exit upon receiving SIGINT, instead of an instant exit during printing.

If you want to catch the signal, you could use this-

#include  <signal.h>

void SIGINT_handler(int sig)
{
     // Ignore the signal's default behaviour
     signal(sig, SIG_IGN);
     // Do graceful printing/cleanup here
     exit(0);
}

Now you need to bind this function to SIGINT, you can do that in main

signal(SIGINT, INThandler);

Note: This is a very simple example just to point you towards the right direction. Since you're using printf inside your code, this will break.

Signal interception during IO is difficult to get right. What if the signal was called in the middle of a printf call? The behavior would likely not be how you want it to be.

More information here

Chase
  • 5,315
  • 2
  • 15
  • 41
  • So input of ^c by the user at any point of the printing process will terminate the process? But i want it to just pause the printing process, verify if really want to exit, then exit, not the whole programme, but to the previous part of the whole code (Just out of the loop). And during the verification, what if the user accidentally clicked ^c, and wanted to continue the printing process? For that situation, id it use `if-else` with `Break;` and `continue;` ? – UnfreeHeX Jun 14 '20 at 07:38
  • @UnfreeHeX in the interception of the signal, you can use any control statements and even IO to confirm whether the user truly wants to exit and all that stuff. Just make sure to use a condition in your `while` loop that is modifiable by the signal handler. So as soon as the signal handler is triggered, it can stop the loop. – Chase Jun 14 '20 at 07:41
  • 1
    Using signals is the right approach. -- But PLEASE read *and understand* the documentation of signal handling. It's ringing a bell that standard I/O in a signal handler might not be the best idea. It might take some experiments until you get it right. Also, you need to read about `volatile` if you plan to use some common variable between the signal handler and your loop. -- One prominent example of signaling I came across many years ago is `dd` that print its current progress when it receives the signal USR1. Perhaps you like to look into its sources. – the busybee Jun 14 '20 at 08:23
  • @UnfreeHeX If you believe this post answers your question, please consider marking this as the answer by clicking on the tick mark next to the votes. This may help people that come looking for your question in the future :) – Chase Jun 17 '20 at 08:09