Skip to main content

Calculating the cost of muffins

Consider the problem of writing a program called muffins that do the following. The program calculates the total cost of buying muffins. The program will do the following:

  • Ask the user to enter the total number of muffins they wish to buy
  • Ask the user to enter the unit price of the muffins (how much does it cost per muffin)
  • Echo the input and display the total cost of muffins with clear breakdowns

Initially, this may seem like a simple calculation that we already know how to do.. just multiply unit price and number of muffins. However, in Canada, there is actually a law around muffins (and other baked goods).

When you buy six or more muffins, those muffins are considered to be groceries and groceries are not taxed. However, if you buy less than 6 muffins, those muffins are snacks... and snacks are taxed.

In Ontario, the HST is 13%. We need to make sure that our program applies this tax law to the calculation.

Here is a sample run of what this would look like if we bought less than 6 muffins:

Please enter the number of muffins purchased: 5
Please enter the price of each muffin: 0.90

Cost of 5 muffins at $0.90 each: $4.50
Taxes: $0.59
Total: $5.09

Here is a sample run if we bough 6 or more muffins:

Please enter the number of muffins purchased: 6
Please enter the price of each muffin: 0.90

Cost of 6 muffins at $0.90 each: $5.40
Taxes: $0.00
Total: $5.40

This sort of situation happens all the time in real life and our programs need to be able to handle. Essentially what we have is two paths through our program. In one path we need to apply tax and in the other path we do not. Our steps can be captured by this flow chart :

In this program, we have a decision to make to determine if we apply taxes or not. This is captured by this part of the flow chart:

if we are buying less than 6 muffins we do one thing, otherwise we do something different.

To implement this in C, we need to use an if/else statement. The syntax of this statement goes like this:

if (<condition>){
//do this block of code if <condition> is truthy
...
}
else{
//do this block of code if <condition> is falsey
}

Start with what we already know how to do:

We can read in data using function similar to what we did in the previous chapter. We can then add a function to calculate the cost of the muffins given the price and number sold and finally we can output the result.

#include <stdio.h>
int getNumMuffins();
double getUnitPrice();
double calculateTaxes(int numMuffins, double unitPrice);
void outputResult(int numMuffins, double unitPrice, double taxes);

// Note how simple this main() function looks. It has the 4 big
// clear steps
// * read how many muffins
// * read unit price
// * calculate total price
// * output result
// We know this is the order we are doing each of these steps.
// The function independently from each other.
// Each function has a clear purpose and if we need to alter something
// it is only in one place. For example.. if we need to adapt
// this program to work in British Columbia, we would need to alter
// the tax rate to 12%. by isolating the tax calculation to one
// function,

int main(void)
{
int numSold = getNumMuffins();
double unitPrice = getUnitPrice();
double tax = calculateTotal(numSold, unitPrice);
outputResult(numSold, unitPrice, tax);
}

The getXX() functions

The user input functions are actually fairly easy to work with. They are similar to the function we wrote in the previous chapter to read in the radius of each sphere. Thus, we simply take that code and adjust it to our current needs:


double getUnitPrice()
{
double unitPrice;
printf("Please enter the number of muffins purchased: ");
scanf("%lf",&unitPrice);
return unitPrice;
}

int getNumMuffins()
{
int numMuffins;
printf("Please enter the price of each muffin: ");
scanf("%d", &numMuffins);
return numMuffins;
}

Output Result:

The entire point of functions is to separate the problems into small pieces. If we know the number of muffins, the unit price and taxes, we can output the result with minimal calculations.

void outputResult(int numMuffins, double unitPrice, double taxes)
{
double subtotal = numMuffins*unitPrice;
printf("Cost of %d muffins at $%.2lf each: $%.2lf\n",numMuffins, unitPrice, subtotal);
printf("Taxes: $%.2lf\n",taxes);
printf("Total: $%.2lf\n",subtotal + taxes);
}

calculateTaxes() function

In this function we need to determine whether or not we bought 6 or more muffins in order to correctly return the taxes. To do this, we can create a condition using one of the comparison operators.

double calculateTaxes(int numMuffins, double unitPrice)
{
double taxes;
//check if number of muffins is less than 6.
if(numMuffins < 6){
taxes = numMuffins*unitPrice*0.13;
}
else{
taxes = 0;
}
return taxes;
}

Putting it all together:

#include <stdio.h>
int getNumMuffins();
double getUnitPrice();
double calculateTaxes(int numMuffins, double unitPrice);
void outputResult(int numMuffins, double unitPrice, double taxes);


int main(void)
{
int numSold = getNumMuffins();
double unitPrice = getUnitPrice();
double tax = calculateTaxes(numSold, unitPrice);
outputResult(numSold, unitPrice, tax);
}
double getUnitPrice()
{
double unitPrice;
printf("Please enter the number of muffins purchased: ");
scanf("%lf",&unitPrice);
return unitPrice;
}

int getNumMuffins()
{
int numMuffins;
printf("Please enter the price of each muffin: ");
scanf("%d", &numMuffins);
return numMuffins;
}
void outputResult(int numMuffins, double unitPrice, double taxes)
{
double subtotal = numMuffins*unitPrice;
printf("Cost of %d muffins at $%.2lf each: $%.2lf\n",numMuffins, unitPrice, subtotal);
printf("Taxes: $%.2lf\n",taxes);
printf("Total: $%.2lf\n",subtotal + taxes);
}

double calculateTaxes(int numMuffins, double unitPrice)
{
double taxes;
//check if number of muffins is less than 6.
if(numMuffins < 6){
taxes = numMuffins*unitPrice*0.13;
}
else{
taxes = 0;
}
return taxes;
}

Alternatives

Our implementation is based on our flow chart where we chose between one of two paths. However, this is not the only solution. Instead of choosing between two paths, we can default to no taxes and only change the taxes if we need to. The flow chart of our program would be modified as follows:

This is a small change but essentially we are saying is that there is a sequence with a default.. however if needed, we can add an extra step... pass through or take a detour.

If we were to implement this flow chart, our calculateTaxes would look like this:

double calculateTaxes(int numMuffins, double unitPrice)
{
double taxes=0;
//check if number of muffins is less than 6.
if(numMuffins < 6){
taxes = numMuffins*unitPrice*0.13;
}
return taxes;
}

Note that this modification of calculateTaxes has no effect on the other 3 functions. This is because the functions are loosely coupled. As long as calculateTaxes() correctly applies the rules of taxation, the rest of the program can use the result as needed. This is a very important concept.