Programming in C

Chapter 2, 6/27/93

The First Program: Compound Interest
The first program we examine will calculate compound interest of a savings account. Certain things in the program won't be explained in great detail the first time around, but just enough to be used; I'll come back to them in greater detail later.
I'll give simple instructions on how to compile and run the program under the Unix environment. Compiling and running under other environments, particularly PC-based ones, is usually simpler, and I refer you to the online help (and the MANUALS!) of your compiler software.
Everything between the two lines consisting of three dashes is part of the text of the program, and you will want to either key it into your editor yourself or clip it out of this message and paste it into the editor (if you're an editing wiz). The three-dash lines themselves lines should *NOT* go into the program. Name the file interest.c. If you're using vi on a Unix system, the command to start editing this file is "vi interest.c", entered at the % prompt without the quotes.
---

/* Note that this text is preceded by a slash and an asterisk.
   This means that this text is a comment, intended to be read
   by you or another programmer looking at your code. The
   comment is ended by another asterisk and another slash.
   Note that you cannot put comments inside comments. */

/* This program calculates the value of a savings account after
   a given number of years, with a given initial investment,
   rate of interest and frequency with which interest is computed. */


/* Get standard input and output functions */
#include <stdio.h>

/* Get standard math functions */
#include <math.h>

int main() {
  /* Initial balance (money in account). Since this value can
    have a fractional part, we declare a float (floating point)
    variable to store it. */
  float initial_balance;

  /* Rate of interest, per year (also a floating point value) */
  float interest;

  /* Number of times interest is compounded each year (interest periods)
    (thus 1.0 is annually, 365.0 is daily) */ 
  float frequency;

  /* Time in years */
  float years;

  /* Total interest periods. This cannot have a fractional part,
    so we declare an integer (no fractional part) variable to store it. */
  int interest_periods;

  /* Current balance. (We store this in a separate place form the
    initial balance, so we will still be able to tell how much money
    we started with when the calculation is finished.) */

  float balance;

  /* Counter of interest periods */
  int i;

  /* Initial values */
  initial_balance = 1000.0;
  interest = .05; /* Five per cent interest */
  frequency = 12.0; /* Compounded monthly: 12 times per year */
  years = 4.0; /* For four years */

  /* Calculate number of interest periods */
  interest_periods = frequency * years;

  /* Set working balance to begin at initial balance. */
  balance = initial_balance;

  /* Loop through interest periods, increasing balance */
  for (i=0; (i < interest_periods); i++) {

    /* Each period, multiply balance by 1.0 plus the annual
      rate of interest divided by the number of times per year
      (frequency) with which interest is compounded. */
    balance = balance * (1.0 + (interest/frequency));
  }
  
  /* Print out result */
  printf("Initial balance: %f Final balance: %f\n", 
    initial_balance, balance);
  
  /* Everything went fine */
  return 0;
}

---
Let's consider the program line by line to learn how it works.
The program begins with several comments. (Anything contained between /* and */ is a comment in a C program.) Comments aren't read by the compiler; they're for your benefit, and for the benefit of other programmers who must read your code.
Next, several #include directives appear.
#include tells the compiler to treat another file as part of your code. Usually this is done to bring in information about common functions that are used in most programs but are not part of the language itself. (Unlike languages such as BASIC, C does not define functions like "print" and "input." Such things are written *in* the language, and have no special powers that your own functions do not have.) There is a standard set of functions to perform input and output, and these are fetched by the #include <stdio.h>line. The #include <math.h>line fetches useful functions for calculations on floating point numbers; we do not actually use any of these special functions in the program as it stands, but it is common practice to include <math.h>when using floating point numbers (numbers with fractions), as some compilers are likely to mishandle them otherwise.
Following the #include directives, the actual program begins.
FUNCTIONS: Every program in the C language is a collection of functions. The purpose of a function is to perform a particular task, large or small. Some functions are defined in the "standard C library", and we inform the compiler we will be using these functions by using the #include directives described above. Others we define ourselves, breaking down the tasks our program must perform into subtasks and writing additional functions to perform those tasks until the program is complete.
Every C program has ONE function called "main". The "main" function is where the program begins; typically the main function calls other functions to perform various tasks until the program's overall goal has been achieved.
The line:
int main() {
begins the main function.
The "int" indicates what kind of value this function will return to the function that called it.
"But this is main()! You just said main() goes first! Nobody calls it!"
Well, not quite -- you call it from the % prompt (or the C> prompt, or the prompt of another operating system). Technically speaking, the "shell" called the program, and the shell can take advantage of the value you return from main to determine whether the program "worked" or not. This is very useful when writing shell scripts (under Unix) or .BAT files (under MSDOS).
The two parentheses after main represent the list of "arguments" (parameters) the function can be called with. Since this is a simple main() function, it takes no arguments, and so there is nothing between the parentheses. (More sophisticated programs *do* take arguments to main(). This will be discussed later.)
The "{" at the end of the line signals the beginning of the actual code making up the function. "{" marks the beginning of a "compound statement" (series of statements making up one unit, to be performed one after the other) in the C language.
Next, in the main() function (and in any function), come the variable declarations.
("Variables", with which you will be familiar if you have worked in any programming language, are needed to store values in your program, and to provide meaningful names by which to refer to those values.)
Consider the line:
float initial_balance;
In order to compute compound interest, we need to know how much money the account starts out with. initial_balance is the variable in which we will store this quantity.
Money amounts often contain fractions, or (if you're lucky) are very large numbers. For that reason, we need to store them as floating-point numbers.
So the word "float" appears preceding the name of the variable.
"float" is a "type specifier". There must always be a type specifier in a variable declaration, and variables MUST ALWAYS BE DECLARED, UNLIKE IN BASIC, which allows variables to be introduced for the first time when they are first actually used. This may seem frustrating, but in fact it helps to structure code, and clear declarations of what type the variable has help to avoid conclusion later on in the code.
Now, NOTE THE SEMICOLON at the end of the line. The semicolon marks the end of the statement.
This is crucial in C. Spaces, carriage returns (new lines) and the like have much less meaning in C than they do in languages such as BASIC. You MUST place a semicolon at the end of a simple statement. (A series of statements enclosed by { }'s is a compound statement; a single statement followed by a semicolon (";") is a simple statement.)
"So if spaces don't matter much, why is your code indented so carefully?"
Because, otherwise, it becomes illegible soup. C does not attempt to tell you to clean up your room, but it does provide you with plenty of breakable toys to trip over. Keeping your code well-organized is the best way to avoid confusing yourself.
The next three lines of code (not including comments) declare additional floating-point variables to be used in the calculation.
Then we encounter the following line:
int interest_periods;
This line declares a variable of type integer. This is because we know there will be a non-fractional number of interest periods that will pass in their entirety during the time over which we are computing interest. Integers typically require less space to store than floating point numbers, and computations involving them are usually faster as well, so when you are certain that a value can be represented by an integer, it is reasonable to declare it as such.
(NOTE: The size of an integer varies, unfortunately, from one environment to the next. The "size" of an integer is the range of values it can represent. In mathematics, we consider an integer to be any real value without a fractional component, but in C, an integer has a maximum and a minimum value. This stems from the fact that each computer has a size of value which it can most comfortably (quickly and efficiently) operate upon, and this size is the size of an integer on that particular model of computer. There are ways to specify larger integers, which will be discussed later.
On an IBM compatible running MSDOS, the value of an integer is usually limited to between -32768 and 32767. On other systems, integers have a much larger range.)
Returning to the code, we next declare two more variables, one a floating point value and the other an integer.
Next, we begin the actual work of the program by assigning initial values to the variables. The line:
initial_balance = 1000.0;
sets the initial balance. Note the use of the = operator, which means assignment ("*make* the left side equal to the right side") in C. There is a separate == operator which is used to *test* for equality. Confusion of the two is the most common error in C programming.
Note also that in assignment statements, as with declarations and all other simple statements, a semicolon marks the end of the statement.
In the following line,
interest = .05; /* Five per cent interest */
Sets the interest rate. Note that a decimal point can begin a number. Note also that a comment can appear on the same line with actual code; this is reasonable for brief comments like the above.
Skipping down several lines, we come to the computation of the number of interest periods that will fall completely within the time over which we are computing interest:
interest_periods = frequency * years;
Note the use of the * operator. The * operator means "multiply" in this situation. It has a second meaning when used in a different context, which will be discussed later.
Skipping a line, we come to the critical part of the program, that in which interest is actually computed:
  for (i=0; (i < interest_periods); i++) {

    /* Each period, multiply balance by 1.0 plus the annual
      rate of interest divided by the number of times per year
      (frequency) with which interest is compounded. */
    balance = balance * (1.0 + (interest/frequency));
  }
Our goal here is to compound the balance once for each interest period. In order to do so, we take advantage of the "for" keyword to create a "loop."
The "for" keyword is always followed by a set of three expressions, all enclosed in an outer set of parentheses.
The first of the three is an assignment statement, in this case i=0. This statement is performed once, at the very beginning of the loop, ensuring that our count of interest periods begins at zero.
The second is a "conditional expression," the first one we have seen. In C, a conditional expression is actually no different from any other expression (computation). If the expression yields a NON-ZERO value (any value EXCEPT zero), it is regarded as "true." If it yields precisely zero, it is regarded as "false." In the expression used here:
(i < interest_periods)
The "<" operator is used to mean "is less than": if the value of i is less than the value of interest_periods, the "<" operator will yield a nonzero value. If i is NOT less than interest_periods, the expression will yield zero. The ">" operator ("is greater than") and the "==" operator ("is equal to"; NOTE THAT THIS IS NOT THE SAME AS A SINGLE "=") are also available, as are ">=" and "<=" ("greater than or equal to" and "less than or equal to"), and "!" (exclamation point), which means "not" (changing a true value to false, or vice versa).
The conditional expression in a for loop is evaluated at the *start* of every pass through the loop. (Note that this means that if the condition is not true on the first pass through the loop, the loop will never execute at all!)
In this case, the condition is used to ensure that we will compute interest once for every interest period; the counter begins at zero, which satisfies the condition, and the process stops when the counter becomes equal to interest_periods.
Since we begin counting from zero, if interest_periods is equal to 4, then on each pass i will be equal to:
0, 1, 2, and finally 3.
Thus we pass through the loop exactly four times.
Now draw your attention to the third and final expression between the parentheses:
i++
(NOTE: the final parenthesis ends this expression, and so a semicolon is not and should not be provided.)
This expression takes advantage of the ++ operator. It appears strange to those used to BASIC or to other languages that do not have such an operator, but in fact it saves a great deal of typing.
Briefly,
i++
is equivalent to:
i = i + 1
and ++ is referred to as the "increment" operator. Note that there is also a "decrement" operator ("--").
Now we are ready to consider what actually takes place *inside* the for loop.
A for loop consists of the for keyword, the three expressions inside the parentheses, and the next statement *following* the parentheses. This following statement can be either a simple statement (one action ending in a semicolon) or a compound statement (a series of statements within { } 's). To avoid losing track of whether the loop is correctly written, it is best to always use a compound statement, even if you only put one simple statement inside it.
Here again is the statement inside the for loop, which is executed once for each pass through the loop:
balance = balance * (1.0 + (interest/frequency));
Note the use of parentheses to group expressions. Their meaning is identical to their usual meaning in algebra. Note also the use of the "/" operator, which means "divide by".
In fact, C follows the standard algebraic order of expressions, with additional rules to cover the unusual operators of C; see Kernighan & Ritchie for a more detailed discussion. I strongly recommend the liberal use of parentheses when you are in any doubt whatsoever as to the order in which operations will take place.
(A note on my arithmetic: the new balance after a given interest period is equal to the current balance, plus the current balance times the annual rate of interest divided by the number of interest periods which will take place in a year. The 1.0 is present to account for the current balance before the multiplication.)
Note that this expression can be made more succinct through the use of the "*=" operator:
balance *= (1.0 + (interest/frequency));
The "*=" operator is similar to the "++" and "--" operators in that it eliminates typing. It means "multiply the left side by the right side and assign this value to the left side." The "+=", "-=" and "/=" operators are also available, and "+=" and "-=" are used particularly often.
A closing "}" ends the compound statement, and thus the entire for loop. When this loop has completed execution, the final balance at the end of the time period is known.
The next statement prints out what has been calculated:
printf("Initial balance: %f Final balance: %f\n", 
  initial_balance, balance);
(Note that this statement is broken across two lines. This is acceptable, and often necessary. Generally the second and subsequent lines should be indented one step further than the first line of such a statement; otherwise considerable confusion results.)
printf() is *not* a keyword, which is to say it does not have a special significance in C, like "for" does. printf() is a function, like main(), or like other functions you will soon write. It is, however, part of the standard C library, and it is made available for use by the #include directive at the beginning of your program.
A function call consists of the name of the function, followed by a set of arguments within parentheses. These arguments will correspond to the arguments that have been declared for that function. (The printf() function is one of a special group of functions which can take a variable number of arguments; users can write such functions also, and this advanced topic will be covered later in the tutorial.)
The first argument is a string. Constant strings are represented in C by a series of characters between double quotes:
"Bob!"
"The answer is %d"
"Hello, Dolly"
are all legitimate strings. If you need to place a double quote *inside* a string, you can do so by using the special \ character, which is used to "escape" the character following it into a string:
"\"Bah, Humbug,\" he said."
(Here two " characters are escaped into the string.)
In the statement under consideration, the escape sequence \n is used. This sequence places a carriage return (a new line) in the string; otherwise subsequent output would print on the same line. So the string:
"Initial balance: %f Final balance: %f\n"
contains a carriage return at the end.
The two %f sequences in the string are used to tell printf() where to print the floating-point values we will be passing to it.
So the values of initial_balance and balance will be substituted for %f at those points.
(The number of % sequences must match the number of arguments actually passed! To output an integer value, the %d sequence would be used instead of %f.)
Now consider the final statement of the program:
return 0;
This statement returns a value of 0 to the calling function. Since this happens to be the main() function, a value of 0, which is generally accepted to mean the program ran successfully and without incident, is returned to the operating system.
A final } matches the { at the beginning of the main() function, and marks the end of the function.
COMPILING THE PROGRAM
We are now ready to compile and test the program.
Enter the program into your editor if you have not already done so, and save it.
Now instruct your system to compile the program.
If you are using an MSDOS-based compiler with a mouse-driven environment, you will probably want to pull down the "Run" menu and select "Run". The program will compile and, if there are no errors, it will execute. (If the program runs and immediately returns, not allowing you to see the results, enter the appropriate command to look at the output screen. For Borland C products, this command is ALT+F5. I believe the command for Microsoft C products is F9.)
If you are running in a Unix environment, you will need to compile your program by entering the following command at the % prompt:
cc interest.c -o interest
(This instructs the compiler to compile the file interest.c and create an executable program called interest. If you have gcc and not cc, then use the gcc command instead.)
If there are no errors, type:
interest
at the % prompt to run the program.
IF THERE ARE ERRORS:
If the program does not compile successfully, look at the error message that has appeared. Use the editor to look at the line number to which the first error message refers, and search for a typo. (I have tested this program, so it is unlikely to produce errors if it has been entered correctly, though I may be wrong!)
If the compiler complains that it cannot find include files, then you need to set your include paths properly. Consult your manuals; in the case of a Unix system ask your administrator or a knowledgeable programmer at your site for assistance.
When you believe you have fixed the problem, try again to compile it; when all goes well, run the program to see the result. Correct output should look as follows, with some slight deviation depending on your model of computer and compiler possible:
Initial balance: 1000.000000 Final balance: 1220.895386
(These results came from Borland Turbo C++ version 1.01.)

<< Previous || Next >>