Curious student
Curious student

Reputation: 3

Is there a way to continue inputs after pressing control+Z?

The scenario is that I want to let the users to input numbers, for however many times they want, and after they press control+Z, they should still be able to input something else.

using namespace std;
int main(){
    int a,b;
    while(cin>>a>>b) cout << a+b<<endl;
    cin >> a;
    cout << a;
}

Although I know that the loop can be terminated by letting the user input something else, but is there anyway to work with inputs after control+Z is pressed?

Upvotes: 0

Views: 715

Answers (2)

Tomek
Tomek

Reputation: 353

Ctrl+Z doesn't terminate your program, but only stops it. Ctrl+Z sends SIGSTOP signal to the process, after which it is in "stopped" state (sort of sleeping), and goes to the background of the terminal. The only way to send more input to it is to first resume it - from the terminal by using the fg command, or programmatically, by sending SIGCONT signal to it (but if the process was executed from a terminal, then the terminal may prevent the SIGCONT signal from reaching your process, effectively allowing you to wake it up only using the fg command).

If you leave the process in "stopped" state, it will be still alive, but sleeping, as long as the terminal is running - in such case, when you close the terminal, you may prevent your program from finishing properly (eg. unsaved data will be lost, etc.).

SIGSTOP cannot be caught or ignored by the process, so there is no way to "disable" Ctrl+Z.

You can, however, prevent the default action of Ctrl+C, which terminates a process (sends SIGINT signal to it). The SIGINT signal can be caught and ignored by your program, effectively making it immune to Ctrl+C:

#include <iostream>
#include <cstring>
#include <signal.h>

int main()
{
    struct sigaction action;
    memset(&action, 0, sizeof(struct sigaction));
    action.sa_handler = SIG_IGN;
    if(sigaction(SIGINT, &action, nullptr) != 0) {
            std::cerr <<  "Failed to modify signal actions: " << strerror(errno) << std::endl;
            return EXIT_FAILURE;
    }

    // ... do your stuff ...

    return EXIT_SUCCESS;
}

Also, instead of ignoring the signal, as in the above example, you can catch it and react accordingly, for instance, saving data that needs to be saved before your program finishes, etc.:

void catch_function(int signal)
{
    std::cout << "Caught signal " << signal << std::endl;
    // do some stuff needed before finishing the app
}

//...

int main()
{
    //...
    action.sa_handler = catch_function;
    //...

It is generally a good idea to catch and react to SIGINT (Ctrl+C) and SIGTERM (kill command) if you don't want to allow the process to finish uncontrollably. There's also SIGKILL signal (kill -9 command), which also terminates your program, but this signal, as Ctrl+Z, cannot be caught or ignored.

Upvotes: 0

Ulrich Eckhardt
Ulrich Eckhardt

Reputation: 17415

No there isn't. The point is that the C++ program only sees a stream of input characters, not any keypresses. When you press control-Z (Note: This depends on the shell/terminal), that stream is cut off outside your program, so nothing inside your program can change that. For all we know, the input could be coming from a file, and what would be the meaning of reading behind the end of a file? It's like reading the page after the last page in a newspaper.

In some cases, you might be able to access the terminal and get closer to key presses using a so-called curses library. There are a bunch out there for different environments, but those things are not part of standard C++.

Upvotes: 5

Related Questions