# Basic Calculator

Show 80 post(s) from this thread on one page
Page 1 of 2 12 Last
• 11-02-2006
Surge
Basic Calculator
Let us begin shall we?

So my assignment for the mid-term this semester is to put together a basic calculator that supports memory functions. I have been getting lots of help from a tutor who uses Borland C Builder. It's funny because - with his help - we were able to get the basic operations to work on Borland, and as soon as I run the program anywhere else, it goes back to skipping my while loop. (Part of it may have to do with the flushall() function that is rarely supported by other compilers.)

I shall present my code:

Code:

```/* C-Calculator by Matthew Nicola */ /* Mid-Term project of M. Fagan's C Programming Class */ #include <stdio.h> #include <conio.h>        /* Might be needed for miscellanious functions */ #pragma hdrstop /*This is where the coding takes place:*/ #pragma argsused int main(void) {     double a, m, v, x;  /* x prevents the loop from breaking */                         /* a is main entry, m is memory, and v is value */     char opr;            /* opr is the operator */         x = 0;     a = 0.0;  /* Calculator Introduction */    printf("Welcome to Matt Nicola's C Calculator!\n");  printf("Enter a value and then enter the operator\n");  printf("to perform an action with the value. Enjoy!\n\n");   /* -----CAUTION: Here comes the loop for operations!----- */         printf("The current value is %lf", &a);             printf("\nPlease enter value: ");         scanf("%lf", &v);             flushall()             printf("\nPlease enter operator: ");         opr = getchar();         while(x != 1)      /* Loop will not be broken until x equals 1 */          {                  if (opr == '+')                    /* Addition */                 a=a+v;         else if (opr == '-')        /* Subtraction */                 a=a-v;         else if (opr == 'X')        /* Multiplication */                 a=a*v;         else if (opr == '/')        /* Division */                 a=a/v;         else if (opr == 'M')        /* Activate Memory */                 a=m;         else if (opr == 'A')        /* Memory Add-on */                 a=a+m;         else if (opr == 'D')        /* Memory Value Deduct */                 a=a-m;         else if (opr == 'C')        /* Clear Current Value */                 a=0.0;         else if (opr == 'E')    /* Option to exit program */                 x = 1;             else                 printf("\nThat operation is invalid.\n");         printf("The current value is %lf", &a);         printf("\nPlease enter value: ");         scanf("%lf", &v);         flushall()         printf("\nPlease enter operator: ");         opr = getchar();           } /* The loop is now completed! Well done! */         printf("Finished!");         return (0); }```
As my instructor checked this out, he emailed me that the coding's pretty bad. He suggested that I apply more detail to the getchar() function and forget about flushall() because Bloodshed can not recognize it. He also says that I must make it ask for the operator first. In addition, the value remains zero for some reason - throughout all activity.

My teacher is a nice guy so he'll understand if I turn in the program late. I shall recieve a small deduction in points upon my return of the fixed coding.

Our textbooks are suppose to apply to the actions of Borland C Builder; the instructor checks everyone's work by using Bloodshed at home. In addition, the labs in our T building do not have it installed so it's harder on us to find an appropriate compiler.

What do you veterans suggest would be my first step into bringing this calculator to life? As you help me out, I shall continue to look for bugs in the code and possibly check some reference links.
• 11-02-2006
Prelude
>What do you veterans suggest would be my first step into bringing this calculator to life?
Start by cleaning up the formatting. Pick something and be consistent with it. Then remove any non-standard features that you use:

>#include <conio.h>
This is a non-standard header. Most people use it for getch, which usually can be replaced with a standard alternative to the same effect.

>#pragma hdrstop
Avoid pragmas if at all possible.

>double a, m, v, x;
Shorter code isn't smaller or faster. Feel free to use descriptive names.

>/* -----CAUTION: Here comes the loop for operations!----- */
After the input? Why should I be cautious? Use your comments carefully.

>printf("The current value is %lf", &a);
%lf doesn't exist for printf, you use %f for both float and double types and %Lf for long doubles. Also, you don't need to use the address-of operator with printf, only with scanf.

The output stream is only flushed when it becomes full, is explicitly flushed, or when you print a newline. In this case, the message may not be seen before scanf starts blocking for input. It's generally a good idea to end your prompts with a newline or an fflush call:
Code:

```printf ( "Please enter a value: " ); fflush ( stdout );```
>scanf("%lf", &v);
Always check the user input for success. scanf returns the number of items you ask for on success:
Code:

```if ( scanf ( "%lf", &v ) == 1 ) {   /* It worked */ }```
>flushall()
There's a missing semicolon after this. But since you should remove it completely anyway, that's a moot point. There are other ways to flush the input stream (not fflush!), which you can find here in the form of myflush.

>while(x != 1)
This is an issue because x is floating-point. You'll find that it's not quite so easy to compare floating-point values for equality. A much better solution would be to make x an integer.

Yea, that should give you a nice start. Keep it up! :)
• 11-02-2006
QuestionC
Ok, so there's a few problems with your code:

Code:

`flushall();`
Technically, flushall() is a macro. Meaning, you don't need a semicolon. Still, you should put one there. Code interpreters (IDEs, beautifiers) sometimes bork if semicolons are missing.

Code:

```#ifndef flushall #define flushall() { while (getchar() != '\n'); } #endif```
This macro is probably what you need to get around the problem of flushall() not being defined in other compilers. It's what worked for mine.

Code:

`printf("The current value is %lf", a);`
Use a, not &a. You shouldn't need to pass the address of arguments to printf.
• 11-03-2006
Salem
Using fgets() and sscanf() pretty much makes all that input stream flushing and "am I using the right compiler" issues go away.

> #define flushall()
Do you know what happens if you enter EOF ?
• 11-03-2006
Surge
Quote:

Originally Posted by Salem

> #define flushall()
Do you know what happens if you enter EOF ?

Ah, I believe EOF is used to signal the "end of file" in text files. I recently learned that in my last chapter. EOF would be the new flushall macro if #define was placed before the two terms. But would an error occured if EOF was fooled with like that?

*sigh* I am such a noob...
• 11-04-2006
CaptainMorgan
In addition to what others have already said, you may consider using a switch statement in place of your if's and else if's statements, and maybe even a do while loop.

In regards to EOF try:

Code:

```while ( (op = getchar()) != EOF ) { ... }```
• 11-04-2006
swgh
EOF usally means pressing ^Z to end a program loop
• 11-04-2006
SG57
Also, to optimize it a bit more - try using switch statements rather than a large quantity of if ... then ... else statements.
• 11-04-2006
CaptainMorgan
Quote:

Originally Posted by SG57
Also, to optimize it a bit more - try using switch statements rather than a large quantity of if ... then ... else statements.

thanks for the echo
• 11-07-2006
Surge
Well here is what I have so far...without the switch statement of which I was just informed.

Code:

```/* C-Calculator by Matthew Nicola */ /* Mid-Term project of M. Fagan's C Programming Class */ #include <stdio.h> #include <conio.h> /*This is where the coding takes place:*/ #pragma argsused int main(void) {     double mainval,        /* The starting value for the program */           memory,        /* Holds memory value for memory functions */           newval,        /* This modifies the main value by operation */           exit1;          /* Prevents breaking of loop */         char  opr;            /* Term for basic functions */         exit1 = 0;     mainval = 0.0;     memory = 0.0;  /* Calculator Introduction */    printf("Welcome to Matt Nicola's C Calculator!\n");  printf("Enter an operator and then enter the value\n");  printf("to correspond with the operator. Enjoy!\n\n");  printf("\nThe current value is 0");      printf("\nEnter the operator to begin: ");  scanf("%lf", &opr);  getchar();         while(exit1 != 1,        /* Loop will not be broken until x equals 1 */           getchar()!= '\n')  /* \n is terminated to prevent a bug */           {              if (opr == '+')                    /* Addition */                 {printf("\n\nEnter a value to add to the current value: ");                 scanf("%lf", &newval);                 getchar();         mainval = mainval + newval;}         else if (opr == '-')        /* Subtraction */             {printf("\n\nEnter a value to subtract from the current value: ");                 scanf("%lf", &newval);         getchar();         mainval = mainval - newval;}         else if (opr == '*')        /* Multiplication */                 {printf("\n\nEnter a value to multiply the current value: ");                 scanf("%lf", &newval);         getchar();         mainval = mainval * newval;}         else if (opr == '/')        /* Division */                 {printf("\n\nEnter a value to divide the current value: ");                 scanf("%lf", &newval);         getchar();         mainval = mainval / newval;}         else if (opr == 'm')        /* Activate Memory */                 {printf("\n\nEnter the value for your memory: ");                 scanf("%lf", &newval);         getchar();         mainval = memory;}         else if (opr == 'a')        /* Memory Add-on */                 {printf("\n\nEnter a value to add to the memory: ");                 scanf("%lf", &newval);         getchar();         memory = memory + mainval;}         else if (opr == 'd')        /* Memory Value Deduct */                 {printf("\n\nEnter a value to subtract from the memory: ");                 scanf("%lf", &newval);         getchar();         memory = memory - mainval;}         else if (opr == 'c')        /* Clear Current Value */                 {printf("\n\nThe current value has been cleared. ");         mainval = 0.0;}         else if (opr == 'e')    /* Option to exit program */         {exit1 = 1;}     else if (opr == '\n')         {printf("\nERROR - Please shut down the program and debug");         printf("\n to fix the character problem.");}     else                 {printf("\nThat operation is invalid.\n");}                     printf("\nCurrent value is %f%8.2", mainval);     printf("\nThe value of your memory is %f%8.2", memory);         printf("\n\nEnter the operator to begin:");     scanf("%lf", &opr);     getchar();                   }         return (0); }```
I guess it is doing the same thing it was in my previous edition: Skipping the loop and assuming an invalid character....wonderful. However, the switches sound like a great idea. I'll look in my text books about those.

EDIT: Darn it! I forgot to take out the newvals from the memory functions.
• 11-08-2006
Happy_Reaper
I think putting a getchar as a flow controller for your while loop is a bad idea. Here's an example why :

First you read opr with scanf. So let's assume you put in 3. The input buffer when it is sent to scanf will look like :

3'\n'

scanf will read your 3. Then the getchar after that will flush the newline. But then you do another getchar in your while loop. So the program waits for input from the user, but the user doesn't have much idea what to input. So he is likely to press 'Enter' (that's the usual panic button) and then you'll read a newline and skip out of the loop.

Also, here :

Code:

`scanf("%lf", &opr);`
You'd probably want %c.

And I don't know what ',' means in your while loop. I'm thinking you want to say &&. But I'm not sure. This is something the vets are likely to know better than me.
• 11-08-2006
Salem
Code:

```                {printf("\n\nEnter a value to divide the current value: ");                 scanf("%lf", &newval);         getchar();         mainval = mainval / newval;}```
1. The position of your braces is very obscure, and hard to follow.
The poor indentation doesn't help either.

Try using a common style such as
Code:

```if ( cond ) {     statements; } else {     statements; } if ( cond ) {     statements; } else {     statements; }```
Also, read the FAQ on using say fgets() and sscanf() to read, then extract information.
Then you can avoid all that getchar() hackery, which doesn't actually work if the user decides to type in a few bonus characters for good measure.
• 11-08-2006
maxorator
This is my style (a mix):
Code:

```if ( cond ) {     statements; } else {     statements; }```
• 11-08-2006
ssharish2005

ssharish2005
• 11-09-2006
Surge
Quote:

Originally Posted by Salem
Code:

```                {printf("\n\nEnter a value to divide the current value: ");                 scanf("%lf", &newval);         getchar();         mainval = mainval / newval;}```
1. The position of your braces is very obscure, and hard to follow.
The poor indentation doesn't help either.

Try using a common style such as
Code:

```if ( cond ) {     statements; } else {     statements; } if ( cond ) {     statements; } else {     statements; }```
Also, read the FAQ on using say fgets() and sscanf() to read, then extract information.
Then you can avoid all that getchar() hackery, which doesn't actually work if the user decides to type in a few bonus characters for good measure.

The notepad interpreted the indenations incorrectly Salem. That wasn't exactly my fault.

But I will fix that up.
Show 80 post(s) from this thread on one page
Page 1 of 2 12 Last