# Thread: Calculator - Past the basics of 2+2

1. ## Calculator - Past the basics of 2+2

I have made a rather simple calculator for every day use, but I hoped to take the calculator one step more and get it to where I can add, subtract, multiply, and divide more than two numbers at a time. For example if you have ever messed around with the python compiler you can actually add, subtract, multiply, and divide more than just two numbers. You can do 2+2+2..., if you want to, instead of only being limited to do just 2+2. I know this would be a rather simple task by making an API and all, but I hope to use this in both linux and windows, plus I need the experience. I have checked at Planet Source Code and a few other places for any example ways to do this, but they only had calculators with APIs or were limited to only adding, subtracting, multiplying, and dividing two numbers at a time.

The problem that I am really running into is that I don't know how to grasp how to really do this with my limited knowledge over the C language. I have thought of maybe doing this by making the inputed information from the user into a string and looking for key word like the =, but it didn't really sound like a really great way to go about doing it. I am going to post the source of my simple calculator that can only add, subtract, multiple, and divide two numbers, to hopefully allow you to get the idea of where I am at in programming in the C language.

Code:
```#include <stdio.h>
#include <math.h>
#include <time.h>

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

int sub (int x, int y)
{
return x - y;
}

int mult (int x, int y)
{
return x * y;
}

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

float sqroot (float x)
{
return sqrt (x);
}

float cosine (float x)
{
return cos (x);
}

float sine (float x)
{
return sin (x);
}

float tangent (float x)
{
return tan (x);
}

float loggy (float x)
{
return log (x);
}

int main()
{
int choice;
int x;
int y;
time_t local;
struct tm *info;

time (&local);
info = localtime (&local);

printf("C Caculator : written by the Rat\n");
printf("Current date and time are:\n %s", asctime (info) );
printf("What would you like to do?\n");
printf("[2]   Subtract\n");
printf("[3]   Multiply\n");
printf("[4]   Divide\n");
printf("[5]   Square Root\n");
printf("[6]   Cosine, Sine, Tangent\n");
printf("[7]   Log\n");
printf("[8]   Quit\n");
scanf("%d", &choice);
if (choice == 1)
{
printf("What two numbers would you like to add?\n");
scanf("%d", &x);
scanf("%d", &y);
printf("The product of your two numbers are : %d\n", add(x,y));
}
else if (choice == 2)
{
printf("What two numbers would you like to subrtract?\n");
scanf("%d", &x);
scanf("%d", &y);
printf("The quotient of your two numbers are : %d\n", sub(x,y));
}
else if (choice == 3)
{
printf("What two numbers would you like to multiply?\n");
scanf("%d", &x);
scanf("%d", &y);
printf("The product of your two numbers are : %d\n", mult(x,y));
}
else if (choice == 4)
{
printf("What two numbers would you like to divide?\n");
scanf("%d", &x);
scanf("%d", &y);
printf("The quotient of your two numbers are : %d\n", divide(x,y));
}
else if (choice == 5)
{
printf("What number do you want to find the sqrt of ?");
scanf("%d", &x);
printf("The answer is : %f\n", sqroot(x));
}
else if (choice == 6)
{
printf("What number is what you want to find ?\n");
scanf("%d", &x);
printf("[1]    Cos\n");
printf("[2]    Sin\n");
printf("[3]    Tan\n");
scanf("%d", &y);
if (y == 1) {
printf("The answer is : %f\n", cosine(x));
}
else if (y == 2) {
printf("The answer is : %f\n", sine(x));
}
else if (y == 3) {
printf("The answer is : %f\n", tangent(x));
}
else	{
printf("Invalid Selection");
}
}
else if (choice == 7)
{
printf("What number would you like to find the log of ?\n");
scanf("%d", &x);
printf("The answer is : %f\n", loggy(x));
}
else if (choice == 8)
{
printf("Bye!\n");
return 0;
}
else
{
printf("Invalid Selection\n");
}
}```
I hope I explained well enough as to where I am trying to head in this project.
Thanks for any help!!!

Revekius

2. You could have a much more usable calculator if it scanned in a string at each prompt. Then it could analyze the string and see what calculations to do, perhaps utilizing string.h. For example, if the input were "3 + 2" it would take the three, assign it to a variable, see the "+" and prepare to add whatever comes next (2). This approach might get a bit complicated, so you might consider using Reverse Polish notation.

3. Well, the most robust extensible solution would be to create a full blown grammar for functions and the like (variables too)--however, that would be a lot of work and an alternative solution is to use a stack based operator precedence parser. Once you decide on the method you can ask more specific questions.

An operator precedence parser in the most basic sense pushes information onto a stack and takes predefined actions based on its current input and what's on top of the stack (which is what it had previously encountered).

4. durt : Yeah I was thinking along those lines, but wasn't sure if it would be the most efficent or best way to go about doing it.

valis : Ahhhh.... I was actually talking to someone else before on how to do this, and they kind of said to go about doing the same thing. He talked about how I could probably use data structures in my program to benefit me more. I can't say I know much over the issue, but I guess that maybe another way to go about doing what I am trying to do. (At least that is what I am thinking the stack operator actually fits in with Data Structures).

Thanks for both of your guys help I will have to check out more about that valis,

Revekius

5. you could have used command line parameters to create a calculator, it might make the code much simpler

6. stormtrooper86 : Isn't there one issue though that you would have to deal with in doing that. Portability ? I was hoping to make it cross platform instead of just using it on windows or linux.

Revekius

7. It could be run on both, but I don't actually see any advantage of using command line arguments unless you wanted to do things like "mul 4 6". You would still need the logic to sort out something like "4 + 3 * 6" to multiply 3 and 6 before adding 4.

8. valis : I looked up and read a little bit more about operator precedence parser and came across this site : http://epaperpress.com/oper/index.html . I was actually looking at the program example and I thought it may do something to the effect of what I was hoping for, but I didn't really get the desired effect. It was doing some weird stuff whenever I did easy problems like 5*6+5, and it outputted 6. Is this the right thing or not? :/

Anyway if it is, I have one big question about the source code. In the source code it shows a chart as follows :

Code:
```char parseTbl[tMaxOp][tMaxOp] = {
/* stk      ------------------ input ------------------------ */
/*         +   -   *   /   ^   M   f   p   c   ,   (   )   \$  */
/*         --  --  --  --  --  --  --  --  --  --  --  --  -- */
/* + */  { R,  R,  S,  S,  S,  S,  S,  S,  S,  R,  S,  R,  R },
/* - */  { R,  R,  S,  S,  S,  S,  S,  S,  S,  R,  S,  R,  R },
/* * */  { R,  R,  R,  R,  S,  S,  S,  S,  S,  R,  S,  R,  R },
/* / */  { R,  R,  R,  R,  S,  S,  S,  S,  S,  R,  S,  R,  R },
/* ^ */  { R,  R,  R,  R,  S,  S,  S,  S,  S,  R,  S,  R,  R },
/* M */  { R,  R,  R,  R,  R,  S,  S,  S,  S,  R,  S,  R,  R },
/* f */  { R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  S,  R,  R },
/* p */  { R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  S,  R,  R },
/* c */  { R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  S,  R,  R },
/* , */  { R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  R,  E4},
/* ( */  { S,  S,  S,  S,  S,  S,  S,  S,  S,  S,  S,  S,  E1},
/* ) */  { R,  R,  R,  R,  R,  R,  E3, E3, E3, R,  E2, R,  R },
/* \$ */  { S,  S,  S,  S,  S,  S,  S,  S,  S,  E4, S,  E3, A }
};```
I understand the main jist of what it is, but other than that I can't say much more. I figured out that it was called : bottom-up shift-reduce parsing. Is Shift, Reduce, and Accept very similiar to the stack functions of Push, Pop, and Peek ? I would probably know this answer if I knew more about data structures, but at the moment I don't.

Thanks for any help,

Revekius

9. Shift means push the current input onto the top of the stack.
Reduce means pop the stuff off of your stack and perform some action with it.
Accept means that the expression was syntactically correct according to your rules.

You can alternatively build a structure, build and walk a tree, optimize or do whatever else you want. However, you will probably just want to perform actions.

I am assuming E1-E4 are exceptions, input isn't syntactically correct, for example )( is not valid.
So you should first figure out what inputs you want to allow and how you want to make your parser (you don't have to make a multidimensional table like that, you could just write actions explicitly, whatever you feel more comfortable with).

I assume you want + - * / digit at least--possibly ( and ) as well. I would also recommend first making a table on paper, all of the above operators are left associative but ^ is right.

Left associativity is like this: 4 + 4 + 4 is (4 + 4) + 4 not 4 + (4 + 4). The second one is right associativity.

So lets say your input is 4 + 3 - 2
- You see a digit and you have \$ (nothing) on your stack, you convert 4 (remember it's '4' (52) not binary 4) and then push it onto your stack of values.
- Then you see a plus, you check your table and see that you should push it onto your empty operator stack.
- Now you see a 3 and you should push it onto your values stack.
- You see a minus and you have a plus on your operator stack. Minus and plus have the same precedence and are left associative, so you should pop the value off the top of your operator stack (+) and you know plus takes two inputs so you pop the top two values off of your stack and add them. Then push that value back onto the values stack.
- Now you see a 2 so you push it onto your values stack.
- You see that you have no more input so you need to reduce, you pop the top value off of your operator stack and see that it's a minus (-) and again you know it takes two inputs, so you pop off the 2 and the 7 and subtract to get 4.

I realize now that this is somewhat long winded and I don't know how helpful it was (if you needed theory or example help) so if I missed something just ask.

10. valsi : I think I understand the general direction of operational precedence, but I am still quesy about it... I just think more reading over the whole subject is something that I need to do.

Thanks for your help again,

Revekius

11. :sigh:

en.wikipedia.org/wiki/Operator-precedence_parser
en.wikipedia.org/wiki/Reverse_Polish_notation

Enjoy.

It was doing some weird stuff whenever I did easy problems like 5*6+5, and it outputted 6. Is this the right thing or not? :/
It used strtok with " " as the token, so you need to enter "5 * 6 + 5" to get the correct result.

12. MDofRockyView : Alright I will check that out.

jafet
: Yeah I have actually already been to those website and have found a prefect example on the forums : http://cboard.cprogramming.com/showt...cedence+parser

Thanks,

Revekius

Popular pages Recent additions