PRACTICE

Practice program 1.

Write a program that calculates the factorial of a number, using a function int fact(int n). The factorial (𝓃!) of a non-negative integer 𝓃 is defined as the product (multiplication) of that number times all the numbers down to 1. The factorial of zero (0!) is 1, and the factorial of one (1!) is also 1. For example, the factorial of five (5!) is 5×4×3×2×1.

We can use our earlier solution, and move the factorial calculation into a function. This cleans up the code quite a bit, as the math to calculate the factorial is now on its own. You can use the factorial function anywhere in your program, just by calling fact(n).

#include <stdio.h>

int
fact(int n)
{
   int iter;
   int factorial;

   /* compute the factorial */

   if (n < 0) {
      return -1;                       /* n! is only defined for n>=0
                                          so this indicates an error */
   }
   else if (n == 0) {
      return 1;                        /* 0! is defined as 1 */
   }
   else {
      factorial = 1;

      for (iter = n; iter > 0; iter = iter - 1) {
         factorial = factorial * iter;
      }

      return factorial;
   }
}

int
main()
{
   int num;

   puts("Enter a non-negative integer:");
   scanf("%d", &num);

   if (num < 0) {
      puts("Oops! That needs to be 0 or greater");
   }
   else {
      printf("%d! is %d\n", num, fact(num));
   }

   return 0;
}

Factorial is only defined for non-negative integers. In theory, the program should test if it is going to calculate factorial of a negative number, and avoid doing so. But in case the function is called with a negative argument, we'll return -1 as an error code.

Practice program 2.

Write a program that calculates the factorial of a number, using a recursive function int fact(int n). This recursive function should calculate fact(n) for any non-negative n as n * fact(n-1), where fact(0) is 1.

When used wisely, recursion can greatly simplify the source code to a function. The factorial calculation is a classic case for recursion. Note that the factorial function is much easier to write using recursion, because we can let the recursive calls do the hard work of calculation. Using recursing, we can replace the iterative calculation with the value return (n * fact(n - 1)).

#include <stdio.h>

int
fact(int n)
{
   /* compute the factorial. uses a recursive call. */

   if (n < 0) {
      return -1;                       /* n! is only defined for n>=0
                                          so this indicates an error */
   }
   else if (n == 0) {
      return 1;                        /* 0! is defined as 1 */
   }
   else {
      return (n * fact(n - 1));
   }
}

int
main()
{
   int num;

   puts("Enter a non-negative integer:");
   scanf("%d", &num);

   if (num < 0) {
      puts("Oops! That needs to be 0 or greater");
   }
   else {
      printf("%d! is %d\n", num, fact(num));
   }

   return 0;
}

While recursion is a neat trick that solves some programs, there are certain tradeoffs in using recursion. In particular, the program needs to do more work and keep more data in memory as it makes the recursive function calls. So I prefer to make an iterative calculation if I can avoid using recursion. But there are some programs that are better tackled through recursion, so this is an important topic to know.

Practice program 3.

In Part 3. Flow control, we wrote a simple version of the FreeDOS PAUSE command, using scanf to read input from the user, one character at a time. Re-write the FreeDOS PAUSE command without using scanf. Display a prompt "Press Enter to continue…" and call the getchar function until you find a newline (\n) character.

The scanf function is a useful method to gather certain kinds of input. But for collecting a single character at a time, scanf has more overhead than we need. The getchar function is much easier, and requires only a one-line change to replace scanf with getchar. And because getchar actually returns an int value, we need to make one more change to our variable definition.

#include <stdio.h>

int
main()
{
   int ch;

   puts("Press Enter to continue . . .");

   /* loop until we find \n (newline) */

   do {
      ch = getchar();
      /* printf("debugging: [%c]\n", ch); */
   } while (ch != '\n');

   puts("Ok");

   return 0;
}

Otherwise, this is the same PAUSE program that we learned in Part 3.