2

I try to create a simple calculator with C. The numbers and operators should be parameters. I already have the main function and a calculate function:

main:

int main(int argc, char *argv[]){
    long result;
    long number1 = strtol(argv[1], NULL, 10);
    long number2 = strtol(argv[3], NULL, 10);

    result = calculate(number1, number2, argv[2]);
    printf("Result: %li", result);

    return 0;
}

calculate:

long calculate(long number1, long number2, char operator){
    long result;

    switch(operator){
        case '+': result = number1 + number2; break;
        case '-': result = number1 - number2; break;
    }
    return result;
}

When I start the program like this:

./calc 1 + 2

the result is 0. I think there is a problem with the operator parameter, because when I write '+' instead of argv[2] it works. But I dont know how to fix it, that it works with the parameter, too.

Nono
  • 1,073
  • 4
  • 23
  • 46

2 Answers2

6

One problem is that your calculate function expects a char, but your main passes a C string. Another problem is that when an unexpected parameter is passed, switch fails to set result, leading to undefined behavior.

One way to get compiler's help in detecting issues like this is to provide prototypes for all functions ahead of the point where the function gets called:

// Put the prototype first
long calculate(long number1, long number2, char operator);

int main(int argc, char *argv[]){
    // main's code with the call of calculate
}

long calculate(long number1, long number2, char operator) {
    // implementation
}

With a prototype in place, the compiler stops the build with an error, because argv[2] does not match the expected type of char. The problem immediately becomes obvious to you, you insert the missing asterisk, and the program starts working as expected.

You are probably seeing a warning about the second issue (not setting result in some code paths); you shouldn't ignore it, and add a default clause that produces some output that tells users what went wrong.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
2

I get warning when I try your code.

$ gcc main.c 
main.c: In function ‘main’:
main.c:19:42: warning: passing argument 3 of ‘calculate’ makes integer from pointer without a cast [-Wint-conversion]
     result = calculate(number1, number2, argv[2]);
                                          ^
main.c:4:6: note: expected ‘char’ but argument is of type ‘char *’
 long calculate(long number1, long number2, char opcode){

After fixing warnings, it seems fine.

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

long calculate(long number1, long number2, char opcode) {
    long result = 0;

    switch (opcode) {
        case '+':
            result = number1 + number2;
            break;
        case '-':
            result = number1 - number2;
            break;
        default: {
            break;
        }
    }
    return result;
}

int main(int argc, char *argv[]) {
    long result;
    long number1 = strtol(argv[1], NULL, 10);
    long number2 = strtol(argv[3], NULL, 10);

    result = calculate(number1, number2, *argv[2]);
    printf("Result: %li", result);

    return 0;
}

Output

$ ./a.out 4 + 4
Result: 8

(But think it could do precedence: $ ./a.out 4 + 4 * 2 Result: 8 In real math, you have operator precedence so a more extensive answer is a grammar for a calculator so that you can have recursive operator precedence. How does a simple calculator with parentheses work?)

Community
  • 1
  • 1
Niklas Rosencrantz
  • 25,640
  • 75
  • 229
  • 424