Home > Net >  Calculator with user defined variables in C language
Calculator with user defined variables in C language

Time:07-03

I hope you are having a nice day. Thank you for taking the time to read my question. I am still a beginner in the C language. My professor has asked me to program a scientific calculator. The calculator should be able to read and store user-defined variables and work with them. for example, I should be able to enter a=5 b=9 etc. after that the program should calculate, for instance, a 1= 6, or a b=14 and show it to the user. Of course, the user decides if the operation is addition, subtraction, division or multiplication. The user should also be able to enter such input: e.g. c=5 9. I have started working on the calculator, unfortunately, I have just been able to only allow the user to define one variable at a time and work with it.

For example:
a=7
7 a=14

That's all I could do. I asked my professor for help and he keeps telling me that I have to to teach the program how to separate between what is before the "=" and what's after it. Thank you in advance for every help or piece of advice you give This is the code I came up with

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

int main() {
    char situation;
    float operand1, operand2;
    char i = 0;
    char ch;
    char op;
    int operand = 0;
    int j, digit, number[10] = {};
    int j2 = 0;
    char str[100] = { 0 };
    while (1) {
        printf("\n\na) To calculate choose me :)");
        printf("\n\nb) If you want to calculate with variables, choose me:");
        printf("\n\nc) To Exit choose me :(\n\n");
        scanf_s("%c", &situation, 1);
        while ((getchar()) != '\n');
        switch (situation) {
        case 'a':
            printf("type in some arithmetic terms : \n");
            scanf_s("%f", &operand1);
            scanf_s("%c", &op, 1);
            scanf_s("%f", &operand2);
            while ((getchar()) != '\n');
            switch (op) {
            case ' ':
                printf("\n\n%.2f   %.2f = %.2f\n\n", operand1, operand2, operand1   operand2);
                break;

            case '-':
                printf("\n\n%.2f - %.2f = %.2f\n\n", operand1, operand2, operand1 - operand2);
                break;

            case '*':
                printf("\n\n%.2f * %.2f = %.2f\n\n", operand1, operand2, operand1 * operand2);
                break;

            case '/':
                printf("\n\n%.2f / %.2f = %.2f\n\n", operand1, operand2, operand1 / operand2);
                break;

            default:
                printf("\n\nERROR!\n\n");
            }
            break;

        case 'b':
            printf("\n\nTo return to the main menu please enter any capital letter of your choosing\n\n");
            printf("\n\nWhen calculating with a variable, please always write the variable on the right side, Thank you. You may start:\n\n");
            do {
                scanf_s("%s", &str, 99);

                for (i = 0; i < 100; i  ) {
                    if (str[i] == '=') {
                        for (j = 0; j < strlen(str); j  ) {
                            ch = str[j];
                            if (ch >= '0' && ch <= '9') {
                                digit = ch - '0';
                                number[j2] = j2 * 10   digit;
                                //printf("%d", number);
                            }
                        }
                        scanf_s("%d", &operand);
                        scanf_s("%c", &op, 1);
                        scanf_s("%d", &number[j2]);
                        while ((getchar()) != '\n');
                        switch (op) {
                        case ' ':
                            printf("\n\n%d   %c = %d\n\n", operand, str[0], operand   number[j2]);
                            break;

                        case '-':
                            printf("\n\n % d - % c = % d\n\n", operand, str[0], operand - number[j2]);
                            break;

                        case '*':
                            printf("\n\n % d * % c = % d\n\n", operand, str[0], operand * number[j2]);
                            break;

                        case '/':
                            printf("\n\n % d / % c = % d\n\n", operand, str[0], operand / number[j2]);
                            break;

                        default:
                            printf("\n\nERROR!\n\n");
                        }
                        break;
                    }

                }
            } while (islower(str[0]));
            while ((getchar()) != '\n');
            break;
        case 'c':
            printf("\n\goodbye\n\n");
            exit(0);
            break;
        default:
            printf("\n\nThis is not an acceptable input. Please Try again!");
        }
    }
}

CodePudding user response:

There are multiple problems in your code:

  • int number[10] = {}; is an invalid initializer in C. You should write:

      int j, digit, number[10] = { 0 };
    
  • you should use double instead of float

  • scanf_s("%c", &situation, 1); is not portable: the Microsoft version of this function expects the size argument 1 as an UNSIGNED whereas the optional Standard C function defined in Annex K specifies that the size argument 1 must be passed as a size_t, hence as (size_t)1. Avoid using this function and read user input as a line with fgets() and use the standard function sscanf() instead and do test the return value to detect and report invalid and/or missing input.

    Add these lines before including <stdio.h> at the top of your source file to prevent compiler warnings:

    #ifdef _MSC_VER
    #define _CRT_SECURE_NO_WARNINGS
    #endif
    
  • scanf_s("%c", &op, 1); does not skip white space, such as spaces and newlines. You should write

      scanf(" %c", &op);
    
  • while ((getchar()) != '\n'); is risky: this loop will run forever if the end of file occurs before a newline can be read.

  • instead of j < strlen(str), which may rescan the string at every iteration, you should write:

      for (j = 0; str[j] != '\0'; j  )
    
  • i is used as an index, it should have type int or size_t, not char.

  • the format string in printf("\n\n % d - % c = % d\n\n", ...); is incorrect: the space between the % and the c is not supported. You probably meant to write this anyway:

      printf("\n\n%d - %c = %d\n\n", operand, str[0], operand - number[j2]);
    
  • printf("\n\goodbye\n\n"); is incorrect: \g is an invalid escape sequence. You should write:

      printf("\n\nGoodbye\n\n");
    

Here is a modified version using functions to parse the line and handle variable assignment separately from evaluating expressions:

#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif

#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* 26 global variables */
double variables['z' - 'a'   1];

void skip_spaces(const char *str, int *pos) {
    while (isspace((unsigned char)str[*pos]))
        *pos  = 1;
}

void trim_spaces(char *str, int *pos) {
    int len = strlen(str);
    while (len > *pos && isspace((unsigned char)str[len - 1]))
        str[--len] = '\0';
    skip_spaces(str, pos);
}

int parse_operand(char *str, int *pos, double *value) {
    char *endp;
    skip_spaces(str, pos);
    char ch = str[*pos];
    if (ch >= 'a' && ch <= 'z') {
        *value = variables[ch - 'a'];
        *pos  = 1;
        skip_spaces(str, pos);
        return 1;  // variable
    }
    *value = strtod(str   *pos, &endp);
    if (endp > str   *pos) {
        *pos = endp - str;
        skip_spaces(str, pos);
        return 2;  // number
    }
    return 0;
}

/* parse an expression with basic operators, no precedence */
int parse_expression(char *str, int *pos, double *result) {
    double operand2;
    char op;

    if (!parse_operand(str, pos, result)) {
        printf("missing operand: %s\n", str   *pos);
        return 0;
    }
    while ((op = str[*pos]) == ' ' || op == '-' || op == '*' || op == '/' || op == '%') {
        *pos  = 1;
        if (!parse_operand(str, pos, &operand2)) {
            printf("missing operand: %s\n", str   *pos);
            return 0;
        }
        switch (op) {
        case ' ':
            *result  = operand2;
            break;
        case '-':
            *result -= operand2;
            break;
        case '*':
            *result *= operand2;
            break;
        case '/':
            *result /= operand2;
            break;
        case '%':
            *result = fmod(*result, operand2);
            break;
        }
    }
    return 1;
}

int main() {
    char str[100];

    printf("type some expressions:\n");
    while (fgets(str, sizeof str, stdin)) {
        double result, result2;
        int pos = 0;

        trim_spaces(str, &pos);
        if (!str[pos]) {
            /* stop on empty line */
            break;
        }
        /* test for a variable assignment */
        if (str[pos] >= 'a' && str[pos] <= 'z' && str[pos   1] == '=') {
            /* variable assignment */
            int v = str[pos] - 'a';
            pos  = 2;
            if (parse_expression(str, &pos, &result) && !str[pos]) {
                variables[v] = result;
                printf("%s -> %.2f\n", str, result);
            } else {
                printf("invalid expression: %s\n", str);
            }
        } else {
            /* other expression */
            if (parse_expression(str, &pos, &result)) {
                skip_spaces(str, &pos);
                if (str[pos] == '\0') {
                    printf("%s -> %.2f\n", str, result);
                } else
                if (str[pos] == '=') {
                    /* comparison of expressions */
                    pos  = 1;
                    if (parse_expression(str, &pos, &result2) && !str[pos]) {
                        if (result == result2) {
                            printf("%s -> true (%.2f == %.2f)\n", str, result, result2);
                        } else {
                            printf("%s -> false (%f != %f, delta: %e)\n",
                                   str, result, result2, result2 - result);
                        }
                    } else {
                        printf("invalid expression: %s\n", str);
                    }
                } else {
                    printf("invalid syntax: %s\n", str);
                }
            }
        }
    }
    return 0;
}

Output:

b=2/3
b=2/3 -> 0.67
2/3=b
2/3=b -> true (0.67 == 0.67)
20/3=10*b
20/3=10*b -> false (6.666667 != 6.666667, delta: -8.881784e-16)
  •  Tags:  
  • c
  • Related