0

How can I exit the program by entering the q character once, not twice?

Why do I need to enter "q" for once more?

I think the expression || scanf("%c", &operation) did not work.

/*
 * Name: Calculator.
 * Description: Calculator for simple math operations.
 *
 * Compiler: Apple LLVM version 10.0.0 (clang-1000.11.45.5).
 * Coding style: Google.
 */

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

#define TRUE 1
#define EXIT 'q'

double add(double x, double y);
double subtract(double x, double y);
double multiply(double x, double y);
double divide(double x, double y);
double degree(double x, int y);
double sqrt(double x);          
double mod(double x, double y);
double div(double x, double y);

int main(void) {
  char *locale = setlocale(LC_ALL, "");

  printf("Examples:\n\n");

  printf("1 + 2\n");
  printf("1 - 2\n");
  printf("1 * 2\n");
  printf("1 / 2\n");
  printf("1 ^ 2\n");
  printf("(sqrt): s 2\n");
  printf("(mod): 1 m 2\n");
  printf("(div): 1 d 2\n\n");

  printf("Input for exit: \"q\"\n\n");

  while (TRUE) {
    double x, y;
    char operation;

    scanf("%lf %c %lf", &x, &operation, &y) ||
        scanf("%c %lf", &operation, &x) || scanf("%c", &operation);

    switch (operation) {
      case ' ':
        break;

      case '\n':
        break;

      case '+':
        printf("Result = %.2lf\n", add(x, y));
        break;

      case '-':
        printf("Result = %.2lf\n", subtract(x, y));
        break;

      case '*':
        printf("Result = %.2lf\n", multiply(x, y));
        break;

      case '/':
        if (y != 0) {
          printf("Result = %.2lf\n", divide(x, y));
        } else {
          printf("\nError!.\n");
        }
        break;

      case '^':
        printf("Result = %.2lf\n", degree(x, y));
        break;

      case 's':
        printf("Result = %.2lf\n", sqrt(x));
        break;

      case 'm':
        printf("Result = %.2lf\n", divide(x, y));
        break;

      case 'd':
        printf("Result = %.2lf\n", divide(x, y));
        break;

      case EXIT:
        printf("Input symbol \"%c\"\nExit...\n", EXIT);
        return 0;
    }
  }

  return 0;
}

double add(double x, double y) { return (x + y); }

double subtract(double x, double y) { return (x - y); }

double multiply(double x, double y) { return (x * y); }

double divide(double x, double y) { return (x / y); }

double degree(double x, int y) {
  int response = 1;
  while (y) {
    if (y & 1) response *= x;
    x *= x;
    y >>= 1;
  }
  return response;
}
iBug
  • 35,554
  • 7
  • 89
  • 134
Dmitry S.
  • 3,766
  • 3
  • 18
  • 26
  • Possible duplicate: https://stackoverflow.com/questions/53248523/c-language-how-can-i-use-backspace-while-using-getchar-in-this-function/53248676. – Petr Skocik Jan 28 '19 at 01:40
  • `scanf(&operation);` is not going to work; that's a single `char`, `scanf` expects a string buffer there – Govind Parmar Jan 28 '19 at 02:07
  • @GovindParmar I think that I should clear buffer after each loop iteration, because I don't know how I can write `scanf` better. – Dmitry S. Jan 28 '19 at 02:18
  • @PSkocik: The question is not a duplicate, and is genuine as per what I understood. The solution, however, is present in the link you shared. – Nitro Jan 28 '19 at 02:43

2 Answers2

2

Your scanf calls will [probably] interfere with one another.

If the first one fails, it will [probably] disrupt the others (i.e. the first one has already pulled the data from stdin, so the others won't see anything).

A surer way is to use fgets and sscanf on the resulting buffer:

 do {
    char buf[1000];

    fgets(buf,sizeof(buf),stdin);

    if (sscanf(buf,"%lf %c %lf", &x, &operation, &y) == 3)
        break;

    if (sscanf(buf,"%c %lf", &operation, &x) == 2)
        break;

    if (sscanf(buf,"%c", &operation) == 1)
        break;

    // error ...
} while (0);
Craig Estey
  • 30,627
  • 4
  • 24
  • 48
0

I think running the code snippet below will answer your question.

#include<stdio.h>


void main(){

double x,y;
char operation='n';
int i;

printf("Enter the variables\n");

i=scanf("%lf %c %lf",&y, &operation, &x);
printf("This is operation, %c and this is long float %lf, this is y %lf  and i %d\n",operation,x,y, i);

i=scanf("%c %lf", &operation, &x);
printf("This is operation, %c and this is long float %lf, this is y %lf  and i %d\n",operation,x,y, i);

i=scanf("%c", &operation);
printf("This is operation, %c and this is long float %lf, this is y %lf  and i %d\n",operation,x,y, i);

}

This is the output I got

Enter the variables
x
This is operation, n and this is long float 0.000000, this is y 0.000000  and i 0
x
This is operation, x and this is long float 0.000000, this is y 0.000000  and i 1
This is operation, x and this is long float 0.000000, this is y 0.000000  and i 1

What is happening is that the first scanf statement reads your input 'q' and discards the buffer as it is not formatted properly and return the 0. Which causes the second scanf to run.

The second scanf reads your 'q' adds it to the operation object, and returns a '1' causing the third scand to not run.

I would suggest the best way to solve this issue, it to keep a standard form of input. Always take characters first, and the doubles later.

Also monitor what scanf returns. It returns the number of identifiers properly parsed.

Nitro
  • 1,063
  • 1
  • 7
  • 17