0

I'm a beginner in programming and I've been trying to make a calculator console app in C for self entertainment, however there has been one minor problem that I thought I could solve easily, but it seems like I'm missing something. I made the system foolproof, as one could say, so you could not type letters instead of numbers and such (I'm bad at explaining, but you get the idea). The problem is that whenever I type the wrong sign and the wrong number B at the same time, both of the error messages appear, which shouldn't happen. I thought it's because of the goto function, which I read isn't very good to use, so I put a check whether an error message has already been shown (bad=1;), which works only with the first number for some reason. What am I doing wrong here?

while (1) {
    double a, b, f=1;
    char znak1;
    int bad;

getagin: 
    bad = 0;
    if(scanf("%lf", &a)) printf("");
    else {
        if(bad == 0) printf("Incorrect number, please write the problem again.\n---\n");
        while(getchar() != '\n');
        bad = 1;
        goto getagin;
    }

    scanf(" %c", &znak1);
    char result[32];
    int n = f;
    if (znak1 == '+') printf("");
    else if (znak1 == '-') printf("");
    else if (znak1 == '/') printf("");
    else if (znak1 == '*') printf("");
    else if (znak1 == '^') printf("");
    else {
        if(bad == 0) printf("Incorrect sign, please write the problem again.\n---\n");
        bad = 1;
        goto getagin;
    }

    if(scanf("%lf", &b)) printf("");
    else {
        if(bad == 0) printf("Incorrect number, please write the problem again.\n---\n");
        while(getchar() != '\n');
        bad = 1;
        goto getagin;
    }
    if (znak1 == '+') snprintf(result, sizeof(result), "%.*f", n, a + b);
    else if (znak1 == '-') snprintf(result, sizeof(result), "%.*f", n, a - b);
    else if (znak1 == '/') snprintf(result, sizeof(result), "%.*f", n, a / b);
    else if (znak1 == '*') snprintf(result, sizeof(result), "%.*f", n, a * b);
    else if (znak1 == '^') snprintf(result, sizeof(result), "%.*f", n, pow(a, b));
    printf("Solved problem: %.*f %c %.*f = %s\n---\n", n, a, znak1, n, b, result);
}
Barmar
  • 741,623
  • 53
  • 500
  • 612
Arko
  • 1
  • 4
    There's no need to use `goto` to go back to the beginning of the loop, use `continue`. – Barmar Sep 30 '17 at 08:04
  • 3
    The `bad = 1;` assignment doesn't work because when you go to `getagin`, it immediately does `bad = 0;`. – Barmar Sep 30 '17 at 08:07
  • See https://stackoverflow.com/questions/1716013/why-is-scanf-causing-infinite-loop-in-this-code for the proper way to check for numeric input. – Barmar Sep 30 '17 at 08:08
  • 1
    Avoid `spaghetti code`, don't use `goto`. – Claudio Cortese Sep 30 '17 at 08:14
  • You might like to read this: [How to debug small programs](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) – alk Sep 30 '17 at 08:15
  • E.g input `6 % 2` ==> `3 * 4`. Since `%` is invalid, it returns first, but in this case it is necessary to clear the remaining input `2`. `2` is used as the next first number and `3` is used as the operator. – BLUEPIXY Sep 30 '17 at 08:15
  • And BTW, only Seniors may use `goto`. ;-) – alk Sep 30 '17 at 08:15
  • 1
    After your error messages, you set `bad` to 1, then you goto `getagin`. Now look at the very first statement after `getagin`: It sets `bad` to 0. So setting it to 1 before branching there served no purpose. You just need to think this through, you have all the information you need - you just need to reason it out. – Tom Karzes Sep 30 '17 at 08:17
  • Thanks everyone, found my problem and solved it. – Arko Sep 30 '17 at 08:18
  • 1
    Also note that if you ever get an EOF while looking for a newline, you will go into an infinite loop. Hint: *Always* check for EOF, and handle appropriately. – Tom Karzes Sep 30 '17 at 08:19
  • When you have a chain of `else if` statements like this, consider using logical operators instead: `if znak1 == '+' || znak1 == '-' || /* ... */ {}`. In this case, you could also use the standard library function `strchr()` from `string.h`: `const char *operations = "+-/*^"; /* ... */ if (strchr(operations, znak1) == NULL) { printf("Invalid operation: %c\n", znak1); /* ... */ } else { /* ... */};` – ad absurdum Sep 30 '17 at 09:38

0 Answers0