/* A simple 'desk calculator' program. Input: Lines of text, each representing an arithmetic expression. Allowed operators are '+', '-', and '*'. No whitespace allowed. All operators have the same priority, no parentheses allowed. A final line commencing with '#' signals the end of the data. Output:At the end of each line, the value of the expression is printed. If input is incorrect, program halts with an error message. */ #include int eval_expr(char next_char, char terminator); main() { /* The following function is needed by main. */ char next_char; /* Holds the first character in a line immediately on entry to eval_expr */ /* Give user instructions... */ printf("Enter expressions, one per line, no blanks. # to finish.\n"); /* Read the first character of the first expression. */ scanf("%c", &next_char); while (next_char != '#') { /* Another expression to process... */ /* Process one calculation (i.e. one line of input). */ printf("Result: %d\n", eval_expr(next_char, '\n')); /* Read first character of following line. */ scanf("%c", &next_char); } return 0; /* success */ } /*********** eval_expr: ********************************* On entry: parameter next_char contains first char of the expression. terminator contains the char expected to end the expression. On exit: If the line is a valid expression, the entire line including its terminator, will have been input and the value of the expression will be returned. If the expression is invalid or the terminator incorrect, an error will have been printed and the program stopped. */ int eval_expr(char next_char, char terminator) { int process_op_operand (int value_so_far, char Operator); /* Note: We can include a function declaration (heading) inside a function. */ int operand_value(char next_char); int value_so_far; /* Holds the progressive calculation result. */ char Operator; /* Holds a character read where an operator is expected. */ /* Evaluate first operand, store in value_so_far.*/ value_so_far = operand_value(next_char); /* Next char should be an operator. */ scanf("%c", &Operator); /* Process operator-operand pairs until terminator seen. */ while (Operator != terminator) { /* The expression continues... */ /* Deal with the operator and its following operand. I.e. compute its effect on value_so_far. */ value_so_far = process_op_operand(value_so_far, Operator); /* Prepare to process next operator */ scanf("%c", &Operator); } /* Expression has been processed and answer is in value_so_far. */ return value_so_far; } /************ process_op_operand: ************************************* On entry: Parameter Operator contains a character from the input, which is supposed to be one of (+, - or *) telling which operation to perform. The following operand has not been read yet. Parameter value_so_far must contain the progressive total for previous calculations. On exit: If operator is not valid, an error message will have been printed and execution stopped. Otherwise, the next operand has been read, and if it is valid, the function returns the updated value so far to reflect this latest calculation. If not valid, an error message is printed and the program stopped. */ #include /* for exit() */ int process_op_operand(int value_so_far, char Operator) { int operand_value(char next_char); char next_char; int new_value; /* The updated value of the calculation after processing this operator. */ /* At this point value_so_far holds one operand, Operator holds the operator. */ switch (Operator) { case '+': scanf("%c", &next_char); /* Get next operand char */ new_value = value_so_far + operand_value(next_char); break; case '-': scanf("%c", &next_char); /* Get next operand char */ new_value = value_so_far - operand_value(next_char); break; case '*': scanf("%c", &next_char); /* Get next operand char */ new_value = value_so_far * operand_value(next_char); break; default: printf("Error: Illegal character: \"%c\".\n", Operator); exit(EXIT_FAILURE); } return new_value; /* Send updated result back to calling function. */ } /********** operand_value: ********************************* On entry: next_char is the first character of the operand. On exit: returns the value of the operand; all characters of the operand have been input. */ int operand_value(char next_char) { int value; if (next_char == '(') { /* A parenthesised subexpression */ scanf("%c", &next_char); /* Get first char of expression */ return eval_expr(next_char, ')'); /* Process expression ending on a ')' */ } else { /* We should have a single number */ if (next_char < '0' || next_char > '9') { printf("Error: \"%c\" should be a digit.\n", next_char); exit(EXIT_FAILURE); } /* Now push that char back into the input, and use scanf. */ ungetc(next_char, stdin); scanf("%d", &value); return value; } }