views:

151

answers:

3

I have a simple console program written in C and want to abort a text input with CTRL + Z. How is it possible?

Edit: Here is some code (untested).

#include <stdio.h>

int main()
{
    float var;

    while(1)
    {
        scanf("%lf", &var); // enter a float or press CTRL+Z

        if( ??? ) // if CTRL+Z was pressed
        {
            break;
        }

        // do something with var
    }

    printf("Job done!");

    return 0;
}
+1  A: 

Basically like this:

if (fgets(buf, sizeof buf, stdin)) {
    /* process valid input */
} else {
    /* Ctrl+Z pressed */
}

There may be complications if you press Ctrl+Z in the middle of the line, but start with the basic.


Edit after OP was updated

You have

scanf("%lf", &var);

scanf returns the number of assignments it did. In your case, you only have 1 variable, so scanf returns 1 in the normal case or 0 when it fails. Just check the return value

int n = scanf("%lf", &var);
/* test the return value of scanf: 1 all ok; 0 no conversions; EOF: error/failure */
if (n != 1)
{
    break;
}

PS: Oh ... the specifier "%lf" in scanf requires a double, var in your program is a float. Correct that too

pmg
I could test it by now. It seems that it doesn't work.
Sven Walter
scanf would return EOF too, if it reaches the end of file, so check for that too. a return value of 0 might just mean the user entered somehing not a float in this case
nos
@nos: In this case I have to press Enter after pressing Ctrl+Z, so I could define a letter (e.g. `q`) to break the loop but I'm searching for something better. B.t.w.: this is not for a real program, but for self-study.
Sven Walter
@Sven: the safest way to get user's input is to `fgets` then `sscanf`.
pmg
To get Ctrl-Z as input on a terminal, that terminal has to have ISIG disabled. Raw mode has ISIG disabled. See the manpage for termios(3).
ninjalj
Okay, I handled it with the scanf return value, becaus I have to code on a Windows machine :-( . Otherwise I would try the POSIX signals.
Sven Walter
Doing it with return value has one big advantage: if (when!) you upgrade your program to accept redirections (rather than direct console input) it is already working.
pmg
A: 

If you're using a UNIX-like operating system, ctrl-z sends a SIGSTOP, which you can generate programmatically, and catch with sigaction.

Chris
+1  A: 

use signal.h to help trap the SIGTSTP sent when you hit CTRL+Z. Note that you'll want to catch SIGTSTP and not SIGSTOP as pausing is a required action for SIGSTOP by only the default action for SIGTSTP.

You may also run into problems not having scanf() return when the signal is generated. Luckily for you, that question has been asked and answered quite nicely already :) http://stackoverflow.com/questions/2512853/scanf-with-signals

jay.lee