1

I have written a code which checks when scanf() returns a negative number, for example if I press "Ctrl+Z" it should get out of the while loop and printf("Finish!") , but instead it is not printing the "finish!" can anybody take a look?

#include <stdio.h>
#include <conio.h>
#include <math.h>

#define G 9.81

float Height(float speed, float angle, float time);
float Horizontal(float speed, float angle, float time);


void main()
{
    float speed;
    float angle;
    float time = 0.1;
    float height = 0;
    float horizontal = 0;
    int res = 0;

    printf("Enter v <0.0 - 100.0 m/s> and a <0-90 degrees>: ");
    res = scanf_s("%f %f", &speed, &angle);
    while (res != -1)
    {
        for (time = 0.1; height >= 0; time += 0.1)
        {
            printf("Time: %.1f .... H = %.2f  S = %.2f \n", time, horizontal = Horizontal(speed, angle, time), height = Height(speed, angle, time));
        }
        height = 0;
        printf("Fallen!\n");
        printf("Enter v <0.0 - 100.0 m/s> and a <0-90 degrees>: ");
        res = scanf_s("%f %f", &speed, &angle);
    }
    printf("\nFinish!\n");
    getch();
}

float Height(float speed, float angle, float time)
{
    float height;
    angle = ((3.14 / 180) * angle);
    height = (speed * sin(angle) * time) - ((G*time*time) / 2);

    return height;
}

float Horizontal(float speed, float angle, float time)
{
    float horizontal;
    angle = ((3.14 / 180) * angle);
    horizontal = (speed * cos(angle)) * time;

    return horizontal;
}

I'm using Visual Studio (C language) on Windows.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Ilan Aizelman WS
  • 1,630
  • 2
  • 21
  • 44
  • Change to `printf("\nFinish!\n");` – nnn Nov 28 '15 at 15:47
  • 1
    Why would scanf() return -1. ( not a rhetorical question, I'm really interested ) ? – Transcendental Nov 28 '15 at 15:48
  • What would scanf() return when you press ctrl+z according to you ? – Christophe Nov 28 '15 at 15:51
  • @Christophe negative number. – Ilan Aizelman WS Nov 28 '15 at 15:51
  • @Transcendental Scanf() Return Value: If successful, the total number of characters written is returned, otherwise a negative number is returned. – Ilan Aizelman WS Nov 28 '15 at 15:51
  • 1
    return value of the scanf function is number of successful conversions, ie. arguments , input conversion. upon failure it returns -1 – Fawzan Nov 28 '15 at 15:52
  • 1
    @IlanAizelmanWS Yes, but why would it fail if you pressed Ctrl + Z? – Transcendental Nov 28 '15 at 15:53
  • 1
    You mention `scanf` in your question, but your code uses `scanf_s`, which is not a standard function (I think it's a Microsoft thing?). I think you're also assuming that `EOF` is -1, which is not guaranteed to be true in general (though it may be in the MS case, I don't know and don't have a compiler handy to check!). The `scanf` function returns the number of *fields assigned* - not characters written - or `EOF` on error, or if when reading the *first* character it gets end-of-file. I think to force an end-of-file condition you have to press Enter-Ctrl+Z-Enter, so that might be the issue? – psmears Nov 28 '15 at 15:56
  • 2
    @Transcendental Because scanf should get 2 floats. if it gets (Ctrl+Z) it is not a float. which means it will return -1 – Ilan Aizelman WS Nov 28 '15 at 15:57
  • @Transcendental: I believe, on windows consoles, Ctrl+Z is the magic incantation to put an end-of-file in standard input, like Ctrl+D often does in linux terminals. –  Nov 28 '15 at 15:59
  • A good idea could be to use a debuger or print out res to see what's happening to confirm/infirm your hypothese – Christophe Nov 28 '15 at 16:08
  • @Fawzan: Note that the C standard says that `scanf()` returns EOF when it encounters end of file, and that EOF is a negative integer. The standard does not say that EOF is `-1`, though that is by far the most common value for EOF. – Jonathan Leffler Nov 28 '15 at 16:30
  • 1
    @psmears "`scanf_s`, which is not a standard function" --> Note: `scanf_s()` is in the C11 normative section `K.3.5.3.4 The scanf_s function` – chux - Reinstate Monica Nov 28 '15 at 17:40
  • @chux still isnt solved – Ilan Aizelman WS Nov 28 '15 at 20:26
  • Exactly what are you typing? Are you hitting control-Z immediately after the first prompt, or some time later? What else have you typed before you type control-Z. Basically, control-Z on Windows (equivalent to control-D on Unix) sends whatever characters are in the input buffer to the program(s) waiting for input. If you've typed nothing else, the programs get told zero bytes read (past tense), which is interpreted as EOF. If you've typed something before hand, the programs may need more input before finishing the `scanf_s()` operation; it depends. _[…continued…]_ – Jonathan Leffler Nov 28 '15 at 20:40
  • _[…continuation…]_ If you've typed anything before you hit control-Z, the `scanf_s()` will return a non-negative value — 0 if it couldn't convert any number, 1 if it only converted one number, 2 if it converted 2 numbers and got information that confirmed that it was at the end of the second number (such as a space). Consequently, if you type `1` and then control-Z, you would indeed have to type control-Z 3 types to make it recognize EOF. If you've typed anything that can't be part of a number (a letter), then you'll never get EOF from `scanf_s()`; your program will go into an infinite loop. – Jonathan Leffler Nov 28 '15 at 20:43
  • Note that the test should be `if (res != 2)`; if you don't get 2 values from the `scanf_s()` operation, something has gone wrong. This might be EOF or it might be 'invalid character'. And the `-1` should be spelled EOF; the `scanf_s()` function returns EOF when it encounters EOF. Granted, EOF is usually `-1`, but it is only guaranteed to be a negative integer value — it is not guaranteed to be `-1`. Of course, since you should be testing for 2, this point is moot. – Jonathan Leffler Nov 28 '15 at 20:48
  • _[…Grumble…]_ Note that these comments of mine show why it is crucial that you put the information in the question about what data you're entering and which platform you're on — these details matter! People can't answer the question accurately if crucial information is missing. – Jonathan Leffler Nov 28 '15 at 20:49
  • @JonathanLeffler I write 12.5 45 as values. and then after I get the result I need to press 3 times Ctrl+Z to see "Finish!" – Ilan Aizelman WS Nov 28 '15 at 20:57
  • Hmm; that needn't be wrong, but it is a bit tricky to explain. When you type `12.5 45` and immediately control-Z, `scanf_s()` can parse the `12.5` and knows it is complete; it can recognize that the `45` is valid so far, but it does not know it has reached the end. You type another control-Z; it gets zero bytes; it knows it has reached the end. So, that's two of the three control-Z's explained. What happens next depends on the standard I/O package and how it handles console input. _[…continued…]_ – Jonathan Leffler Nov 28 '15 at 21:11
  • _[…continuation…]_ If it takes the 'zero bytes read' as EOF and sets the file to the EOF state, then you shouldn't need a third control-Z. On the other hand, it might not latch the EOF state and would wait until you typed another control-Z and it gets zero bytes again before setting EOF. Or it might continue to retry as long as you try to get more input from the console. On Mac OS X, the second control-D latches the EOF state. I don't know what happens on Windows. – Jonathan Leffler Nov 28 '15 at 21:15
  • Note how hard it is to use `scanf_s()` accurately. It is superficially easy, but when you delve into details, it is incredibly complex to get right and remarkably easy to get wrong. I wish people weren't taught `scanf()` or `scanf_s()` — it would so often be so much easier if people used `fgets()` and then `sscanf()` or `sscanf_s()` instead. One of the many benefits is that you can give better error messages when you've got the whole line of input to report as erroneous. Another benefit is that if the line doesn't parse one way, you can try parsing it other ways. – Jonathan Leffler Nov 28 '15 at 21:19
  • @JonathanLeffler Well, I've switched to scanf. what do you suggest to do to solve the problem? – Ilan Aizelman WS Nov 28 '15 at 21:22
  • `scanf()` is not a solution; it is essentially the same as `scanf_s()`. I'm not sure what your problem is at the moment — the code behaves itself as expected. If you want to use a different input system, that's fine. Or simply hit return after the two numbers; then hit control-Z once on the next iteration. That should suffice. What's the hangup on hitting control-Z? – Jonathan Leffler Nov 28 '15 at 21:24
  • ֲ@JonathanLeffler I want my program to print "Finish!" when the user clicks Ctrl+Z once, that is it. – Ilan Aizelman WS Nov 28 '15 at 21:52

3 Answers3

1

Here the reference for scanf(): http://www.cplusplus.com/reference/cstdio/scanf/

When scanf() encounters end of file (that's the usual meaning of ctrl+z on the console), it is not a matching error: it's only that a part of the expected items could be read.

Make your while use >0 instead of >=0.

Christophe
  • 68,716
  • 7
  • 72
  • 138
  • Doesn't help. Btw, I'm using Visual Studio (c language), and I've added the full code in the post now. btw, after I press 3 times Ctrl+z it prints Finish. – Ilan Aizelman WS Nov 28 '15 at 17:53
0

Be sure to press Enter after Ctrl+Z. By default, the terminal input is line-buffered, and it is passed to the program when newline is encountered.

Also, most probably you are running the program in a separated terminal window, which closes when the program exits. This would explain the need for getch(); at the end, to be able to see the output, and then close the window with a keypress.

By default, printf is buffered and the output is written to the terminal when newline \n is reached. The buffer is also flushed when the program exits (exit call or main return). In your case, it will be printed after you press a key, and you may not be able to see it, because the window closed.

To solve this, add a newline character at the end:

printf("\nFinish!\n");
nnn
  • 3,980
  • 1
  • 13
  • 17
  • Doesn't help. Btw, I'm using Visual Studio (c language), and I've added the full code in the post now. btw, after I press 3 times Ctrl+z it prints Finish. – Ilan Aizelman WS Nov 28 '15 at 17:53
0

I believe it should work. Even with >= in while. Definitely works on unix with ordinary scanf().

What IDE and compiler are you using? Are you running this directly through cmd.exe? I'd suggest checking Having troubles with EOF on Windows 7 Also as mentioned in other answers add:

printf("\nFinish!\n");
Community
  • 1
  • 1
J91321
  • 697
  • 1
  • 7
  • 19
  • Doesn't help. Btw, I'm using Visual Studio (c language), and I've added the full code in the post now. btw, after I press 3 times Ctrl+z it prints Finish. – Ilan Aizelman WS Nov 28 '15 at 17:53
  • You also changed the condition in while, I think the >= in it was actually good and works at least with standard scanf. Now it looks like first two times you press Ctrl-Z it ends in &speed and &angle 3rd time it actually terminates the loop. – J91321 Nov 28 '15 at 18:09
  • I changed scanf_s to scanf , doesnt help either. – Ilan Aizelman WS Nov 28 '15 at 18:11