0

Hi so I've created a simple calculator and in my scanf() function what can i do so that if nothing is entered by the user ( or if the user inputs the Enter key ) I want the program to end.

#include<stdio.h>
int main(){
    int a, b;
    char choice;
    while(1){
        printf("Enter your input: ");
        scanf("%d %c %d", &a, &choice, &b);
        switch(choice){
            case '+':
                printf("%d %c %d = %d", a, choice, b, a+b);
                break;

            case '-':
                printf("%d %c %d = %d", a, choice, b, a-b);
                break;

            case '*':
                printf("%d %c %d = %d", a, choice, b, a*b);
                break;

            case '/':
                printf("%d %c %d = %d", a, choice, b, a/b);
                break;

            default:
                printf("Error calculating! Exiting.\n");
                return 0;
                break;
        }
        printf("\n");
    }
    return 0;
}
2hexed
  • 7
  • 4
  • 3
    You can't do this with `scanf()`. Use `fgets()` to read a whole line, and check if that's empty (it will just contain a newline character). – Barmar Nov 22 '21 at 18:30
  • 2
    Then use `sscanf()` to parse the line. – Barmar Nov 22 '21 at 18:31
  • You are faced with a miniature version of a rather classic engineering tradeoff: What do you do when Marketing's requirements for the product are either unreasonable, or too difficult to implement? Are you stuck implementing the required requirements no matter what, or can you lobby for any sort of compromise? Here, you are *not going to be able* to achieve the "Enter should terminate" requirement while sticking with your implementation choice of using `scanf`. So you're either going to have to change the requirement to "non-numeric input terminates, but Enter continues", or punt `scanf`. – Steve Summit Nov 22 '21 at 18:44
  • Input processing should be tolerant of users' foibles too, for example inputting unnecessary spaces or tapping Enter a couple of times first. – Weather Vane Nov 22 '21 at 18:50
  • Aside: `%s` was the wrong format specifier, it should be `%c`. – Weather Vane Nov 22 '21 at 18:51
  • @SteveSummit okay then, I'll remove the part where we press enter to terminate the program, how do I check if all the arguments are given to the scanf function, and also how do I check if the given `a`, `b` arguments are integers and `choice` a char value. – 2hexed Nov 22 '21 at 19:12
  • @WeatherVane oh okay let me change it to `%c` – 2hexed Nov 22 '21 at 19:13
  • 2
    Please see [What does the scanf function return?](https://stackoverflow.com/questions/10469643/what-does-the-scanf-function-return) – Weather Vane Nov 22 '21 at 19:15
  • Does this answer your question? [What does the scanf function return?](https://stackoverflow.com/questions/10469643/what-does-the-scanf-function-return) – Chris Nov 22 '21 at 19:28

1 Answers1

0

You have to separate it into two different actions -- first reading (with fgets for example) and then parsing with sscanf.

Initially I thought that checking the return value of scanf would work but apparently for empty input (or any amount of whitespaces) it will keep reading until it gets a non-digit (thanks for pointing that out in comments).

aragaer
  • 17,238
  • 6
  • 47
  • 49
  • 2
    The problem states the program should end if the user presses Enter. If the user presses Enter, `scanf("%d %s %d", &a, &choice, &b);` will continue reading until it sees a non-white-space character that cannot match `%d`. It will not return any value because it will not return, so this cannot be detected by checking the return value of `scanf`. – Eric Postpischil Nov 22 '21 at 18:36
  • You are right, I should have checked that first. – aragaer Nov 22 '21 at 18:43
  • It's an easy mistake to make. I was about to recommend just checking `scanf`'s return value, also. IMO, having the program exit on plain Enter is an awkward/unnecessary/inappropriate requirement anyway. If the program were specified to exit on a ing containing non-numeric input (like "x" or "done"), but do nothing on plain Enter, the straightforward check-`scanf`'s-return-value solution would work just fine. – Steve Summit Nov 22 '21 at 18:45
  • hi, firstly how can I return all the values passed to the `scanf` function and secondly is there a way to use the `sscanf` function without creating a whole new variable and storing my input in that variable and then using it in the `sscanf`? – 2hexed Nov 22 '21 at 19:04
  • You can't use `sscanf` without first reading the data into a buffer. So you have to declare a variable (buffer) and read data into it. – aragaer Nov 22 '21 at 19:55
  • `char buffer[1024]` is a reasonable sized buffer (character array) that can handle all but the cat sleeping on the keyboard. (on embedded systems, reduce accordingly). Read with `fgets()` into `buffer` and then `if (sscanf (buffer, "%d %c %d", &a, &choice, &b) == 3)` you know you have full input. – David C. Rankin Nov 22 '21 at 20:01
  • @DavidC.Rankin hi so I made my code work by checking the return value of the scanf function in my code but when a user inputs anything the script is there waiting for them to enter the value even though they press the `Enter` key, I want the program the stop taking the user input after they hit enter, how can I do that? – 2hexed Nov 23 '21 at 17:15
  • `while(1){ ... }` will loop forever. So as soon as you press Enter, the `switch()` runs and `scanf()` is called again where it "blocks" waiting for the next input. `scanf()` will NOT read whitespace using the `"%d"` *conversion specifier* ( `'\n'` is whiatespace). All conversion specifiers except `"%c"`, `"%[..]"` and `"%n"` discard leading whitespace. Which is why reading with `fgets()` is a far-superior approach, not just something that avoids a number of pitfalls for the new C programmer. `fgets()` will read `'\n'` when Enter is pressed allowing your `switch()` to hit the `default` case. – David C. Rankin Nov 24 '21 at 02:13
  • Or you can simply do `while (fgets (buffer, sizeof buffer, stdin) && *buffer != '\n') { ... }` which will automatically break the read-loop when Enter is pressed. This because the first character in `buffer` (e.g. `*buffer` or equivalently `buffer[0]`) will hold `'\n'` if Enter alone is pressed for input. That is the key to `fgets()`, it reads an *entire* line of input, including the `'\n'` generated by the user pressing Enter. – David C. Rankin Nov 24 '21 at 02:19