Thread: Basic Calculator

  1. #1
    Registered User
    Join Date
    Nov 2006
    Location
    Rockdale, IL
    Posts
    11

    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.

    Advantages
    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.

    Disadvantages
    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.

  2. #2
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >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.

    >printf("\nPlease enter value: ");
    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!
    My best code is written with the delete key.

  3. #3
    Registered User
    Join Date
    Sep 2001
    Posts
    752
    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.
    Callou collei we'll code the way
    Of prime numbers and pings!

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    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 ?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Nov 2006
    Location
    Rockdale, IL
    Posts
    11
    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...

  6. #6
    Drunken Progammer CaptainMorgan's Avatar
    Join Date
    Feb 2006
    Location
    On The Rocks
    Posts
    45
    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 ) {
    
    ...
    
    }

  7. #7
    Its hard... But im here swgh's Avatar
    Join Date
    Apr 2005
    Location
    England
    Posts
    1,688
    EOF usally means pressing ^Z to end a program loop

  8. #8
    Registered User
    Join Date
    Jun 2006
    Posts
    45
    Also, to optimize it a bit more - try using switch statements rather than a large quantity of if ... then ... else statements.

  9. #9
    Drunken Progammer CaptainMorgan's Avatar
    Join Date
    Feb 2006
    Location
    On The Rocks
    Posts
    45

    Wink

    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

  10. #10
    Registered User
    Join Date
    Nov 2006
    Location
    Rockdale, IL
    Posts
    11
    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.
    Last edited by Surge; 11-07-2006 at 06:27 PM.

  11. #11
    Fear the Reaper...
    Join Date
    Aug 2005
    Location
    Toronto, Ontario, Canada
    Posts
    625
    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.
    Teacher: "You connect with Internet Explorer, but what is your browser? You know, Yahoo, Webcrawler...?" It's great to see the educational system moving in the right direction

  12. #12
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    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.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  13. #13
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    This is my style (a mix):
    Code:
    if ( cond ) {
        statements;
    } 
    else {
        statements;
    }
    "The Internet treats censorship as damage and routes around it." - John Gilmore

  14. #14
    Registered User ssharish2005's Avatar
    Join Date
    Sep 2005
    Location
    Cambridge, UK
    Posts
    1,732
    use switch statements, it made your code more neater and easy to read

    ssharish2005

  15. #15
    Registered User
    Join Date
    Nov 2006
    Location
    Rockdale, IL
    Posts
    11
    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.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Basic Calculator I made check it out if you want...
    By Sshakey6791 in forum C++ Programming
    Replies: 8
    Last Post: 01-08-2009, 12:20 AM
  2. Basic calculator program in C++
    By linkofazeroth in forum C++ Programming
    Replies: 70
    Last Post: 08-28-2005, 04:23 PM
  3. need help with my basic c++ calculator
    By iCouch_Potato in forum C++ Programming
    Replies: 4
    Last Post: 03-24-2004, 06:23 PM
  4. Replies: 2
    Last Post: 05-10-2002, 04:16 PM