Techno-Plaza
Site Navigation [ News | Our Software | Calculators | Programming | Assembly | Downloads | Links | Cool Graphs | Feedback ]
 Main
   Site News

   Our Software

   Legal Information

   Credits

 Calculators
   Information

   C Programming

   Assembly

   Downloads

 Miscellaneous
   Links

   Cool Graphs

   Feedback Form

C Programming Lessons

TIGCC Programming Lessons

The following is part of a series of lessons designed to help teach people to program in C for the TI-89, 92+, and V200 calculators using the TIGCC development environment.

If you wish, you can download the program source code, project files, and binaries here.

Lesson 4: Functions

Step 1 - An Introduction to Functions

Functions are the building blocks of C programs. They encapsulate pieces of code to perform specific operations. Functions allow us to accomplish the same or similar kinds of tasks over and over again without being forced to keep adding the same code into your program over and over again. Functions perform tasks such as string printing (i.e. the DrawStr() and printf() functions), keyboard reading functions (OSdequeue(), ngetchx(), and kbhit()), graphics drawing (Sprite8(), Sprite16(), and Sprite32()), and any other task that will need to be repeated many times. Even though we did not write any of these functions, and do not how they are written, we can still use them. And we can use them over and over again without ever being forced to include the code in our program multiple times.

Functions allow us to put pieces of code together to accomplish a specific task, and then assign an appropriate name to that task so we do not have to copy the code. This makes programming much much easier by allowing us to reuse code from other people, simply by including their functions. This is how the TIGCC library works. It did not write many of the functions we use, it simply provides an interface for us to use the built-in system routines from the AMS software which powers the calculator. I hope it has already been properly illustrated how this can speed up programming significantly. In the times before we had this kind of access, we had to write all these functions by ourselves. The most powerful adage you will ever learn in computer programming is "Don't reinvent the wheel". If you're unfamiliar with this, it just means, if someone else has already done what you are trying to do, then don't waste your time trying to duplicate the same thing. Just use theirs! This is the power of modular function based programming.

Step 2 - An Overview of C Functions

In C, functions are defined in 4 pieces:

  1. the function return type,
  2. the function name (which must be unique),
  3. the functions arguments, and
  4. the function prototype.

Let's examine a simple function declaration: int random(int randmax). The first three pieces have been outlines in green, purple, and red. Let's examine them further:

The function return type is the type of value the function will return when it is called. Many functions will return values that give the user some indication of what happened. These can be values like true (which in C is usually 1), and false (0), or they can be values the function has calculated or found for us (like the ngetchx() function returns the keycode), or it may not return a value at all. In this case, the function return type is void, which means, we do not return a value. So if we had a function void PrintNumber( int number), it would not return any value at the end of the function.

If a function has a return type, you can store that return type in a variable by using the statement: variable = function(arguments); We have seen this before, as in key = ngetchx(); But the ngetchx() function takes no arguments.

The function name is the name we give to the function. It can be anything, so long as it is unique. This means you cannot duplicate the name of any other function you define, and you cannot duplicate the name of any function you have included. This means if you use the TIGCC library, you cannot define a function called DrawStr(), or printf(), or ngetchx(), or any other function that is used by the TIGCC library. This is because the C compiler cannot differentiate between the various functions.

The function arguments are values we pass to the function so it can use them to do its work. If we choose to print a string, we need to know what string to print. Functions can take any number of arguments, so long as they are properly configured. The argument list is a series of variables separated by a comma. So, if we have one variable, the argument list is like this (type varName). If we have two, then it looks like (type var1, type var2), where type is the variable type (int, char, float, etc).

The last part of a proper function declaration is the function prototype. This is what we use to tell the compiler how this function should look when it finds it. It is primarily used because you may be using functions that have not been linked or compiled yet. This is how the TIGCC library works. We do not have the functions we use from the TIGCC library, because they are defined already in the AMS. But the compiler still has to know about them, so we setup a series of prototypes so the compiler will understand that this function exists somewhere. That is all we need to worry about, because the linker takes care of finding the functions we don't define (like those in the TIGCC library).

A function prototype for a particular function should be declared either at the top of a C source file, or in a C header file (a .h file). We haven't used our own .h files yet, but we will be doing so in this lesson. Header files simply store information for the program source code. They hold things like #define directive values, and special types and structures (which we will cover in a future lesson), function prototypes, external variable declarations, and other things we may cover in the future.

So, what is a function prototype? Simple, it's just the signature of a function (i.e. the return type, name, and arguments) with a trailing semi-colon (it's a statement in C, and all statements end in a semi-colon, as you should know). However, in declaring function prototypes, we do not need to know the names of the arguments, only the types. So, if we have the function int random(int randMax) { // some code here }, its function prototype would be:

int random(int);

If we have multiple arguments, we can separate their types with commas, but we do not need names. For example, the function void DrawStr(int x, int y, char *str, int attribute) { // enter code here } becomes:

void DrawStr(int, int, char *, int);

Do not forget the '*' asterisk in the character pointer. Otherwise, the compiler will think we want a single character, when we really want a pointer to a character. If the compiler does not know what to look for, it cannot identify the function, and it will complain. C doesn't like not knowing about something, so you always have to make sure it has all the information it needs.

This also works with type modifiers, as in the function long int double(long int single) { // code }. This would become:

long int double(long int);

You will see more in the example program, and it's easier to illustrate that way, so I will forego any further examples, because they are just too numerous. If you want more examples, take a look at the Nibbles 68k Source Code in the nibbles.h file, and you will see the function prototypes for the nibbles.c file.

Step 3 - A Simple Example Program Using C Functions

Open TIGCC and start a new project. Create a new C Source File called mathtest. Now we need to create a new Header File. The process is very similar to creating a C Source File. Select the File Menu, then the New option, then the C Header File option. You can name this mathtest as well. Here is the code for our two files.

mathtest.c


/*
   MathTest 1.0
   A Simple Mathematics Test Program to Illustrate the Use of Functions in C
   Copyright (C) 2000,2007 Techno-Plaza

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2
   of the License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include <tigcclib.h>
#include "mathtest.h" // include our special header file

// return double the value of the argument
int times2(int number) {
    return (number * 2);
}

// returns the square of the number given
int square(int number) {
    return (number * number);
}

// returns the base number raised to the power of the exponent
long int power(int base, int exponent) {
    int loop;
    long int bigNumber = base;

    // since exponentials are just multiplication the number of
    // the exponent, loop and multiply
    for (loop = 1; loop < exponent; loop++) {
        bigNumber*=base;
    }

    // return this big number
    return bigNumber;
}

// return the sum of the numbers from start to end
int sum(int start, int end) {
    int loop, sum = 0;

    // keep track of the sun
    for (loop = start; loop <= end; loop++) {
        sum+=loop;
    }

    // return the calculated sum
    return sum;
}

// return a number between 0 and 9 based on user input
short int getNumber(void) {
    short int key = 0;

    // wait for valid input
    while (key < '0' || key >'9') {
        key = ngetchx();
    }

    // calculate the number 0 as the value of keycode minus
    // the value of the keycode '0'
    key -= '0';

    // return the corrected number
    return key;
}

// pause the program
inline void pause(void) {
    printf("Press any key...");
    ngetchx();
}

// Main Function
void _main(void)
{
    int done = 0, number, base, exponent, start, end;
    long int bigNumber;
    short int key = 0;

    // loop until we're finished
    while (!done) {
        // clear the screen
        clrscr();

        // display the messages using printf
        printf("Pick a Function or\nPress ESC to Quit\n\n");
        printf("1: Double\n2: Square\n3: Exponent\n4: Sum\n\n? ");

        // wait for valid input
        while ((key < '1' || key > '4') && key != KEY_ESC) {
            key = ngetchx();
        }

        // if we pressed ESC, invalidate the loop
        if (key == KEY_ESC) {
            done = 1;

            // go to the next loop iteration
            continue;
        }

        // calculate the numeric value of the keycode and print
        // the selection
        key -= '0';
        printf("%d\n\n", key);

        // perform actions based on the input
        switch (key) {
            // we chose the double function (times2() function)
            case 1:
                // wait for input and display the selection
                printf("Enter a number (0-9) ? ");
                key = getNumber();
                printf("%d\n\n", key);

                // calculate the value and print the result
                number = times2(key);
                printf("If you double the number\n");
                printf("%d, you get %d\n\n", key, number);

                // exit the switch statement
                break;

            // we chose the square() function
            case 2:
                // wait for input and display the result
                printf("Enter a number (0-9) ? ");
                key = getNumber();
                printf("%d\n\n", key);

                // calculate the value and print the result
                number = square(key);
                printf("If you square the number\n");
                printf("%d, you get %d\n\n", key, number);

                // exit the switch statement
                break;

            // we chose the exponent function (power() function)
            case 3:
                // ask for the base number
                printf("Choose base (0-9) ? ");
                key = getNumber();
                base = key;

                // print the result
                printf("%d\n", key);

                // ask for the exponent
                printf("Choose exponent (0-9) ? ");
                key = getNumber();
                exponent = key;

                // print the result
                printf("%d\n\n", key);

                // calculate the value and print the result
                bigNumber = power(base, exponent);
                printf("If you raise the number\n");
                printf("%d to the power of %d, you\n", base, exponent);
                printf("get the number %ld\n\n", bigNumber);

                // exit the switch statement
                break;

            // we chose the sum function
            case 4:
                // ask for the start number
                printf("Choose Start Number? ");
                key = getNumber();
                start = key;

                // print the result
                printf("%d\n", key);

                // ask for the end number
                printf("Choose End Number? ");
                key = getNumber();
                end = key;

                // print the result
                printf("%d\n\n", key);

                // if we have valid input
                if (end >= start) {
                    // calculate the value and print the result
                    number = sum(start,end);
                    printf("If you summed the numbers\n");
                    printf("from %d to %d, you would\n", start, end);
                    printf("end up with the number %d\n\n", number);
                } else {
                    // otherwise yell at the user
                    printf("You have made an invalid\n");
                    printf("selection. Try again.\n\n");
                }

                // exit the switch statement
                break;
        }

        // pause the program so the user can see the result
        pause();
    }
}

Now edit the mathtest header file. You can do this in much the same way as you do the mathtest source file, just by clicking on the mathtest file name on the source tree in the left window pane under the Header Files. Edit this file so it looks like this:


/*
   MathTest 1.0
   A Simple Mathematics Test Program to Illustrate the Use of Functions in C
   Copyright (C) 2000,2007 Techno-Plaza

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2
   of the License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

/*
    Begin function prototyping here
*/

// returns the value of its argument times 2
int times2(int);

// returns the square of its argument
int square(int);

// returns the first argument raised to the
// power of the second argument
long int power(int, int);

// returns the sum of the numbers between the
// first argument and the second argument
int sum(int, int);

// gets a number between 0 and 9 from the user
// using keyboard input
short int getNumber(void);

// displays a short pause messsage and waits
// for user input before continuing
inline void pause(void);

// the entry point of the program
void _main(void);

/*
    End of Function Prototypes
*/

You need to add an #include directive in your C Source File when you make your own header files. You'll notice we have done this at the top of our C Source File.

Step 4a - Compile and Run the Program

Now save the project and all the files, then build it and send it to TiEmu. Run the program, and you will see something very similar to this:

TI-89 AMS 2.05 mathtest.89z TI-92+ AMS 2.05 mathtest.9xz

Step 4b - Program Analysis

You knew we would be getting here sooner or later. We covered the basic outlines of functions in C, and you have seen how they are used in practice by using functions like ngetchx() and DrawStr(), so this lesson should be very simple. It is presented here mainly as a way to cover all the bases of functions explicitly.

You will notice a slight difference between this example program and example programs from the past. This one does not have all the code contained inside the _main() function. This is because we are now learning how to make real programs, and real programs rarely put all the code into the _main() function. They branch it out into several functions to accomplish tasks without being forced to duplicate code. If you have the same (or very similar) code in more than one place, it's likely to be inefficient. It's better to define a function for such a segment of code and contain it in one place. This makes programs smaller and cuts down on memory usage.

Continue the Analysis in Part II

 

Copyright © 1998-2007 Techno-Plaza
All Rights Reserved Unless Otherwise Noted

Get Firefox!    Valid HTML 4.01!    Made with jEdit