Click here to Skip to main content
15,887,776 members
Please Sign up or sign in to vote.
1.00/5 (2 votes)
See more:
Write a program that carries out simple mathematical operations entered as a command-line strings named 'calc'.
Your program will take a single argument and examine the text to determine if the command is correct and if so, compute it.

Implementation
You will receive a single prefix arithmetic expression in text via argv[1]. You can presume operators and operands will be space-separated. You should check to make sure the operation is possible (i.e. no dividing by zero) and is correctly formatted (i.e. has exactly two operands).
Your operands are: Your operators are: Your errors are:
zero plus Error: not an operator: <text>
one minus Error: not an operand: <text>
two multiply Error: not enough operands
three divide Error: too many elements
four Error: divide by zero
five
six
seven
eight
nine
Common arithmetic expressions with the operator in betwene the operands are called "infix". Prefix notation puts the operand first, so "one plus two" is the infix version and "plus one two" is the prefix version. Be careful to apply context-sensitive operators (like minus and divide) in the correct direction, for example "3 - 1" in infix is equivalent to "minus three one" in prefix and not "minus one three".
You can presume you'll have a single simple expression. There will be no subexpressions, so every expression should have exactly three words: an operator followed by two operands.
Once you decode the expression, you should compute it and output the result in double precision (%2.2ld) and return 1.
If you find an error, you should print an error message and return -1.

e.g.
./calc "plus two three"
5.00

./calc "divide two four"
0.50

./calc "two plus three"
Error: not an operator: two

./calc "divide five zero"
Error: divide by zero

./calc
Error: not an operator:

./calc "plus two three four"
Error: too many elements

Notes:

Putting a command line argument in double quotes makes it a single argument, even if it contains spaces.

This type of operation, where you have many equivalent possibilities, often lends itself very well to a switch statement.

In order to recognize the different number strings, you may want to check out the strcmp() function. Be careful, it only compares one entire string to another. Make sure anything you give to strcmp() is a string.

When you have labels that you want to convert to a value, it may be helpful to use definitions.

Keep in mind every expression has the same format: operator, a space, an operand, a space, and then the last operand. You can expliot this structure to give your code shape.

Keep in mind every error is a failure in an expectation. So, if you are expecting an operand first and you find none, print your error message and return. There is no need to continue. Most error messages are essentially 'else' (or default) cases while you are trying to decode the expression. Some errors (like divide by zero) you need to do a little work to find.

Remember you need to actually compute the result. You should always compute as doubles. Be careful! If you do math with integer values like "2", C can do odd things to type. Make sure all your integers end in decimals (i.e. "1.0" and not "1") in order to make sure you have floating point math.

Implement your code in phases! Don't try to do it all at once. First recognize/decode the operator, add in simple error detection for operator issues. Once that is done add in finding the first operand and simple error checking for it, and then the second operand. Then see if you can compute the operation. Once you have that part working, you are close to done. Add in any other error detection you may have missed.

What I have tried:

C
#include<stdio.h>
#include<string.h>
  
 int getoperd(char str[]){
  char num[11][20]={"zero","one","two","three","four","five","six","seven","eight","nine"};
  for(int i=0;i<11;i++){
   if(strcmp(num[i],str)==0){
       double r=
return r;}
}
 }

int main(int argc,char* argv[])
{
    int counter;
    char op[20],op1[20],op2[20];
    strcpy(op,argv[1]);
    strcpy(op1,argv[2]);
    strcpy(op2,argv[3]);
    if(argc>4)
    printf("Error: too many elements\n");
    else if(argc<4)
    printf("Error: not enough operands");
    else if(strcmp(op,"plus")!=0&&strcmp(op,"minus")!=0&&strcmp(op,"multiply")!=0&&strcmp(op,"divide")!=0)
    printf("Error: not an operator");
    else if(strcmp(op1,"one")!=0&&strcmp(op1,"two")!=0&&strcmp(op1,"three")!=0&&strcmp(op1,"four")!=0
    &&strcmp(op1,"five")!=0&&strcmp(op1,"six")!=0&&strcmp(op1,"seven")!=0&&strcmp(op1,"eight")!=0
    &&strcmp(op1,"nine")!=0&&strcmp(op1,"zero")!=0){
     printf("Error: not an operand");}
  else if(strcmp(op2,"one")!=0&&strcmp(op2,"two")!=0&&strcmp(op2,"three")!=0&&strcmp(op2,"four")!=0
    &&strcmp(op2,"five")!=0&&strcmp(op2,"six")!=0&&strcmp(op2,"seven")!=0&&strcmp(op2,"eight")!=0
    &&strcmp(op2,"nine")!=0&&strcmp(op2,"zero")!=0){
     printf("Error: not an operand");}
   else if(strcmp(op,"divide")==0&&strcmp(op2,"zero")==0)
    printf("Error: divide by zero");
   else{
     if(strcmp(op,"plus")==0){
     int p1=getoperd(op1);
     int p2=getoperd(op2);
     double r=p1+p2;
     printf("%2.2lf",r); 
     }
 else if(strcmp(op,"minus")==0){
     int p1=getoperd(op1);
     int p2=getoperd(op2);
     double r=p1-p2;
     printf("%2.2lf",r); 
     }
else if(strcmp(op,"multiply")==0){
     double p1=getoperd(op1);
     double p2=getoperd(op2);
     double r=p1*p2;
     printf("%2.2lf",r); 
     }
else if(strcmp(op,"divide")==0){
     double p1=getoperd(op1);
     double p2=getoperd(op2);
     double r=p1/p2;
     printf("%2.2lf",r); 
     }
    }
    return 0;
}
Posted
Updated 31-Oct-21 18:30pm
v2
Comments
Patrice T 31-Oct-21 23:36pm    
And you have a question ?

1 solution

You have a function that you should make more and better use of instead of all the literal comparisons you have in your logic. This is the one I mean and it has an error in it.
C++
int getoperand( char str[] )
{
    char * num[]= { "zero","one","two","three","four","five","six","seven","eight","nine", NULL };
    for( int i=0; num[i]; ++i )
    {
       if( strcmp(num[i],str)==0 )
       {
           return i;
       }
    }
    return -1;
}
The function was revised to return -1 if the value passed was not found which means it is invalid. You can use that to verify the numbers like this :
C++
int p1 = getoperand( op1 );
if( p1 < 0 )
{
   printf( "Error: parameter 1, '%s', was not an operand\n", op1 );
   return 1;
}
You can add similar logic to valid the second parameter.

Also, I would omit the logic checking of the operation and take care of it later like this :
C++
   if( argc > 4 )
   {
       printf("Error: too many elements\n");
       return 1;
   }
   else if(argc<4)
   {
       printf("Error: not enough operands");
       return 1;
   }

   int p1 = getoperd(op1);
   // use logic shown previously here

   int p2 = getoperd(op2);
   // use logic shown previously here  

   if(strcmp(op,"plus")==0)
   {
       double r = p1 + p2;
       printf("result is : %5.3lf\n",r); 
   }
   else if(strcmp(op,"minus")==0)
   {
       double r = p1 - p2;
       printf("result is : %5.3lf\n",r); 
   }
   else if(strcmp(op,"multiply")==0)
   {
       double r = p1 * p2;
       printf("result is : %5.3lf\n",r); 
   }
   else if(strcmp(op,"divide")==0)
   {
       // casting is required here to get a floating point result

       double r = (double) p1 / (double) p2;
       printf("result is : %5.3lf\n",r); 
   }
   else
   {
       printf( "Error - '%s' is not a valid operation\n", op );
       return 1;
   }
   return 0;
}
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900