Warning: Cannot modify header information - headers already sent by (output started at /mnt/112/sdb/a/6/biotrans/includes/fonctions.php:1) in /mnt/112/sdb/a/6/biotrans/includes/conf.php on line 165

Warning: Cannot modify header information - headers already sent by (output started at /mnt/112/sdb/a/6/biotrans/includes/fonctions.php:1) in /mnt/112/sdb/a/6/biotrans/includes/conf.php on line 166

Warning: Cannot modify header information - headers already sent by (output started at /mnt/112/sdb/a/6/biotrans/includes/fonctions.php:1) in /mnt/112/sdb/a/6/biotrans/includes/conf.php on line 167

Warning: Cannot modify header information - headers already sent by (output started at /mnt/112/sdb/a/6/biotrans/includes/fonctions.php:1) in /mnt/112/sdb/a/6/biotrans/includes/conf.php on line 177

Warning: Cannot modify header information - headers already sent by (output started at /mnt/112/sdb/a/6/biotrans/includes/fonctions.php:1) in /mnt/112/sdb/a/6/biotrans/includes/conf.php on line 178

Warning: Cannot modify header information - headers already sent by (output started at /mnt/112/sdb/a/6/biotrans/includes/fonctions.php:1) in /mnt/112/sdb/a/6/biotrans/includes/conf.php on line 179
Bio Trans

See another lesson

Retour au menu

Quiche Team

Lesson 6 – Procedures and function


1) Procedure
2)
The different kinds of variables and the constants
3) Parameters
4) Functions
5)
The recursivity



        The procedures and the functions are very useful and powerful. It is able to decrease the size of your code and so your program. In fact, each time you want to make a copy and a paste, you must wonder whether you use a procedure. The big difference between a procedure and a function is: a procedure runs only a part of your code and a function runs a part of your code and returns a value when the function is over. Now after this short introduction I am going to explain how it works and when you must use so as to optimize your code.


1) Procedure

        In fact, a procedure is able to separate a part of your code and after you can call this part of your code very easily. That is why you should avoid coping and a pasting, you can decrease the size of your code and you can more easily read your code. As I have told you in the introduction, each time you want to copy and paste, you should wonder whether it is very useful or if a procedure is more convenient and efficient.
        The syntax of simple procedures is very simple:
    void name ( ) {
    statement
    }

        ‘name’ is of course the name of your procedure. The word ‘void’ means it is a procedure and not a function or rather the function returns nothing: void, this function is a procedure; it is the definition :-). The statement is the part of your code that you want to separate. And the syntax to call a procedure is:
    name ( );
        If you are a good viewer, you can see ‘void _main(void)’ looks like a procedure. Indeed, ‘void _main(void)’ is a procedure and it is the main procedure because it called in first by the compiler. Besides, you cannot delete this procedure or else the compiler does not know to start another procedure.
        Now we can see where you locate the procedure in your code. You have two choices. The easiest, which means you do not need to declare your procedure, is when you write your procedure before the ‘_main(void)’ procedure. The second possibility is to write your procedure after the ‘_main(void)’ procedure’ but you have to declare your procedure before the ‘_main(void)’ procedure. The declaration is simple enough: ‘void name( );’. In fact, the compiler reads the code as a man who reads a European language; what means the compiler reads from left to right and from top to bottom. That is the reason why the compiler has already seen your procedure if you have written it before the ‘_main(void)’ procedure.
        To illustrate this point, I have written three simple codes to see the differences between without and with procedure and the two ways to write your procedures in your code. I will explain the declaration of variables within a procedure in the next point.

Example1 without procedure:


                         


  // C Source File
  // Created 26/02/2003; 17:12:58

  #define USE_TI89              // Compile for TI-89
  #define USE_TI92PLUS          // Compile for TI-92 Plus
  #define USE_V200              // Compile for V200

  #define OPTIMIZE_ROM_CALLS    // Use ROM Call Optimization

  #define MIN_AMS 100           // Compile for AMS 1.00 or higher

  #define SAVE_SCREEN           // Save/Restore LCD Contents

  #include <tigcclib.h>         // Include All Header Files

  // Main Function
  void _main(void)
  {
    int a;

    clrscr();

    for (a = 0; a < 10; a++) {
      printf("*");
    }
    printf("\n");
    for (a = 0; a < 10; a++) {
      printf("*");
    }

    ngetchx();
  }


Example2 with one procedure and without declaration of this procedure:


                         


  // C Source File
  // Created 26/02/2003; 17:14:28

  #define USE_TI89              // Compile for TI-89
  #define USE_TI92PLUS          // Compile for TI-92 Plus
  #define USE_V200              // Compile for V200

  #define OPTIMIZE_ROM_CALLS    // Use ROM Call Optimization

  #define MIN_AMS 100           // Compile for AMS 1.00 or higher

  #define SAVE_SCREEN           // Save/Restore LCD Contents

  #include <tigcclib.h>         // Include All Header Files

  void star() {
    int a;

    for (a = 0; a < 10; a++) {
      printf("*");
    }
  }

  // Main Function
  void _main(void)
  {
    clrscr();

    star();
    printf("\n");
    star();

    ngetchx();
  }


Example3 with one procedure and with the declaration of this procedure:


                         


  // C Source File
  // Created 26/02/2003; 17:17:31

  #define USE_TI89              // Compile for TI-89
  #define USE_TI92PLUS          // Compile for TI-92 Plus
  #define USE_V200              // Compile for V200

  #define OPTIMIZE_ROM_CALLS    // Use ROM Call Optimization

  #define MIN_AMS 100           // Compile for AMS 1.00 or higher

  #define SAVE_SCREEN           // Save/Restore LCD Contents

  #include <tigcclib.h>         // Include All Header Files

  // declaration of your procedure
  void star();

  // Main Function
  void _main(void)
  {
    clrscr();

    star();
    printf("\n");
    star();

    ngetchx();
  }

  void star() {
    int a;

    for (a = 0; a < 10; a++) {
      printf("*");
    }
  }


        Of course, you can also declare your procedure in the second example but it is not a compulsory.
       We have seen we call a procedure in the main procedure but you can also call a procedure in any other procedure. When you use the first way to use a procedure, the compiler has to read the procedure before calling it or else it does not know it and it crashes! That is why the second way with the declaration of procedure is friendlier because you do not need to be careful with the sort of your procedures. The longer and more complex the code, the better it is for the second solution and I strongly advise its use. Later we will see how create a file where you locate all declarations of procedures and it is very clear with complex code!
        When you call a procedure, the Tios takes long. Some times, the procedure is very small or you do not want to loose time to activate it but you want to use a procedure so as to make a clearer code and avoid a copy and a paste; therefore you can make an inline procedure. In fact, the inline procedure is exactly like a copy and paste but it is not you who work but the compiler which makes it instead of you. So you can take advantage of the procedure pros and avoid the procedure cons. It is great!
        The syntax of inline procedure is as simple as a simple procedure: you add only the word ‘inline’ in first position:
    inline void name ( ){
    statement
    }

        When you declare an inline procedure, you must also add the word ‘inline’ like: ‘inline void name ( );’ it is very easy! :-) For example, the following code gives you at the screen the same result than with the others examples.


                         


  // C Source File
  // Created 01/03/2003; 13:38:50

  #define USE_TI89              // Compile for TI-89
  #define USE_TI92PLUS          // Compile for TI-92 Plus
  #define USE_V200              // Compile for V200

  #define OPTIMIZE_ROM_CALLS    // Use ROM Call Optimization

  #define MIN_AMS 100           // Compile for AMS 1.00 or higher

  #define SAVE_SCREEN           // Save/Restore LCD Contents

  #include <tigcclib.h>         // Include All Header Files

  inline void star() {
    int a;

    for (a = 0; a < 10; a++) {
      printf("*");
    }
  }

  // Main Function
  void _main(void)
  {
    clrscr();

    star();
    printf("\n");
    star();

    ngetchx();
  }


        Of course, if you want to exit your procedure before the usual end, you can add: ‘return;’ and you exit the procedure at this moment. It is interesting when you have conditions and according the events you choose to exit or not your procedure.
 

2) The different kinds of variables and the constants

        When you can see in the previous examples, there are also declarations of variables within procedures; it is like with the _main procedure. In fact, if the declaration of your variable is within a procedure, this variable is called ‘local’ variable and it is available only within this procedure. We can say: the variable is born with ‘{‘ and is dead with ‘}’. What means you can declare a variable within any which statement, for instance, a for statement and this variable will be only available for this statement. Of course, it is also right for the main procedure. These variables are called ‘automatic’ variables and it is the default variable.
        If you want to keep the data of your variable after the ‘}’ symbol, you have to add ‘static’ in your declaration of your variable thus you have not an automatic variable. The syntax is:
static type name
        If you have understood what I have explained, you can use a local variable only within the same procedure or statement. However, if you want to use a variable in all the procedures, you have to use another type of variables. This type is called ‘global’. A global variable is available anywhere what means you can use this variable in all procedures and all files but we have not seen this point yet. The declaration of a global variable is as simple as a local variable; only the place of the declaration is different. You have to declare a global variable just after the start of your code: after the include area. I advise you to use the less global variable than you can because your code is more organized.
        I am going to explain something but it is not a piece of advice and you will avoid making it. As we have already seen, there are two types of variables: local and global. In fact, the local variable is more important than the global variable what means when you call two variable with the same name, within the procedure the data of your variable has the data of your local variable and not one of your global variable. It is very clear for the compiler but it is very hard for an human!
        There are two kinds of constants: the constants which are like a copy and a paste and the constants which seem like a variable. The first kind of constant is easier to use according to me. The syntax is:
    #define name value
        Remember the spaces in c language have no signification but it is more visually attractive, isn’t it? The place of this declaration is at the top of your code, after the include area. In fact, it is like with the inline procedure: each time the compiler sees the name of your constant within your code, it replaces the name of your constant by its value. I prefer this kind of constant, I think it is clearer and simpler. The syntax of the second kind of constant is:
    const type name = value;
        The difference with the other constant is that the compiler keeps a memory storage to stock the value. In fact, this constant is like a variable which you cannot change the value.
        We can see an example to understand how all these notions work.


                         


  // C Source File
  // Created 09/03/2003; 12:09:03

  #define USE_TI89              // Compile for TI-89
  #define USE_TI92PLUS          // Compile for TI-92 Plus
  #define USE_V200              // Compile for V200

  #define OPTIMIZE_ROM_CALLS    // Use ROM Call Optimization

  #define MIN_AMS 100           // Compile for AMS 1.00 or higher

  #define SAVE_SCREEN           // Save/Restore LCD Contents

  #include <tigcclib.h>         // Include All Header Files

  #define const1          56

  int global = 17;

  void procedure () {
    int local_procedure = 5;
    int local = 21;

    printf ("local_proc = %d\n", local_procedure);
    printf ("global = %d\n", global);
    printf ("local = %d\n", local);
    // the compiler doesn't know the 'local_main' variable
    printf ("const1 = %d\n", const1); // this constant is like a global constant
    // the compiler doesn't know the 'const2' constant
  }

  // Main Function
  void _main(void)
  {
    int local_main = 13;
    int local = 27;
    const int const2 = 54;

    clrscr();

    printf ("Within the 'main' procedure:\n\n");
    printf ("local_main = %d\n", local_main);
    printf ("global = %d\n", global);
    printf ("local = %d\n", local);
    // the compiler doesn't know the 'local_procedure' variable
    printf ("const1 = %d\n", const1); // this constant is like a global constant
    printf ("const2 = %d\n", const2); // this constant is like a local constant

    ngetchx();

    clrscr();

    printf ("Within the procedure:\n\n");
    procedure ();

    ngetchx();
  }

 

3) Parameters

        The parameters of procedures are very powerful and increase the use of procedures. In fact, you can make your own function, for instance you can make your own function: ‘printf’ but the real interest is you make procedures specific at your program; you can also use these procedures in others programs if these procedures are very useful for you. Indeed you can make your own library but we will see it later! A perfect procedure has to be able to use in any code, what means you must copy and paste only, you change nothing.
        As I discussed before, when we use the notion of parameters, we have to speak about pointers. Indeed, there are two kinds of parameters: by reference or address and by value. We are going to start with the parameters by value because it is the simplest to understand and we do not use pointers.


a) Parameters by value

        We can see the syntax:
    void name ( type name1, type name2, …) {
    statement
    }

and when we call a procedure:
    name (X1, X2, …);
with Xi = value, variable, pointer (with the star acronym ‘*’)
        As you can see, you must declare the parameters like a simple variable: you tell the compiler the type of your parameters. The name of theses parameters is parameters by value because you give at your parameters only the value of variable or just a value. In fact, at the end of your procedure the parameters by value give back nothing. If you change the value of your parameters within the procedure, the parameters assign no variable. To simplify we can see a brief example:


                         


  // C Source File
  // Created 12/03/2003; 17:07:41

  #define USE_TI89              // Compile for TI-89
  #define USE_TI92PLUS          // Compile for TI-92 Plus
  #define USE_V200              // Compile for V200

  #define OPTIMIZE_ROM_CALLS    // Use ROM Call Optimization

  #define MIN_AMS 100           // Compile for AMS 1.00 or higher

  #define SAVE_SCREEN           // Save/Restore LCD Contents

  #include <tigcclib.h>         // Include All Header Files

  #define height            5 // it's a constant to change easily the height of your object

  void star (int number) {
    int a;

    for (a = 0; a < number; a++)
      printf("*");
    printf("\n");
  }

  void space (int number) {
    int a;

    for (a = 0; a < number; a++)
      printf(" ");
  }

  // Main Function
  void _main(void)
  {
    int i;

    clrscr();

    for (i = 0; i < height; i++) {
      space (height - i);
      star (i * 2);
    }
    for (i = height; i > 0; i--) {
      space (height - i);
      star (i * 2);
    }

    ngetchx();
  }


        You can see that if you do not use the procedures, your code would be bigger because you would have to make two “copy & paste” and in addition your code would be very much less readable. I think you understand this example or else you must read the lesson about ‘for’ loop. :-)


b) Parameters by address or reference

        The difference is when you exit your procedure, the parameters by address get the last value within the procedure. In fact, the value of your parameter after the running of your procedure depends on the code of your procedure. Indeed, the parameter does not store the value when you call a procedure but the address. That is the reason why when you assign the parameter within the procedure, you assign the address and you change the value of this address. As we work with the address, we have to use the pointers. In fact, the parameters by address or reference are pointers and when we call a procedure, we use a pointer or else we give the address of your variable. With the parameters by address we have to use a variable or a pointer, we cannot use only a value. After this small introduction, we can see the syntax:
    Void name (type *name1, type *name2, …) {
    Statement
    }

and the syntax to call a procedure:
    name (X1, X2, …);
with Xi = address what means a pointer without the star acronym: ‘*’ or a variable with the dereference acronym: ‘&’.
        When you use the dereference acronym, it is to get the address of your variable and it is just you need with the parameter by address. When you can see in the syntax, there are only parameters by address but it is not a compulsory and you can, use parameters by value and there is no sorting. To illustrate this point as usual usually, I have written a code to compare the both different parameters. Remember that you would play with notions you have learned, it is the best solution to master the programming. A lot of fun! :-)


                         


  // C Source File
  // Created 13/03/2003; 17:16:24

  #define USE_TI89              // Compile for TI-89
  #define USE_TI92PLUS          // Compile for TI-92 Plus
  #define USE_V200              // Compile for V200

  #define OPTIMIZE_ROM_CALLS    // Use ROM Call Optimization

  #define MIN_AMS 100           // Compile for AMS 1.00 or higher

  #define SAVE_SCREEN           // Save/Restore LCD Contents

  #include <tigcclib.h>         // Include All Header Files

  void addition (int x1, int x2, int *answer) {
    *answer = x1 + x2;
    x1 = 3;
    x2 = 5; // these variables are modified only within this procedure
  }

  void change (int *x, int *y, int *z) {
    int aux;

    aux = *x;
    *x = *y;
    *y = aux;
    *z = 27;
  }


  // Main Function

  void _main(void)
  {
    int a, b, c;
    int *sum;
    c = 13; /* you have to initialize also this variable or else when the code is running,
               this variable haven't address */
    sum = &c; // the pointer have to initialize for the same explication

    clrscr();

    a = 13;
    b = 4;
    addition (a, b, &c); // you want to give the address of your variable so you use '&'
    printf ("13 + 4 = %d\n", c);


    addition (17, 4, sum);/* you want to give the address of your pointer so you don't use 
                             //the '*' acronym, it's the definition of a pointer */
    printf ("\n\n17 + 4 = %d", *sum);

    ngetchx();
    clrscr();

    printf ("initial value:\n a = %d\n b = %d\n c = %d", a , b, c);
    change (&a, &b, &c);
    /*
    the procedure gets the address of these variables and it modifies the data of these address
    at the end of procedure, the address is available within the procedure and the out of 
    the procedure 
    */
    printf ("\n\nfinal value:\n a = %d\n b = %d\n c = %d", a , b, c);

    ngetchx();
  }

 

4) Functions

        In fact, a procedure is a function which returns no value: ‘void’. If you want to use a function, you have to tell the compiler which type of value you want. The syntax is:
    type name ( parameters by value or address ) {
    statement
    }

        Of course, using parameters is not a compulsory. When you want to call a function, it is like a procedure: you write in your code: ‘name( );’ but as you use a procedure, it is to get a value thus you have to assign a variable, to display the value at the screen, … you can make hardly like with a variable. Within the function, you must tell compiler the value which the function returns or else the function is useless and the compiler notes a mistake. The syntax is:
    return (value);
Let us illustrate this point!


                         


  // C Source File
  // Created 09/03/2003; 14:03:53

  #define USE_TI89              // Compile for TI-89
  #define USE_TI92PLUS          // Compile for TI-92 Plus
  #define USE_V200              // Compile for V200

  #define OPTIMIZE_ROM_CALLS    // Use ROM Call Optimization

  #define MIN_AMS 100           // Compile for AMS 1.00 or higher

  #define SAVE_SCREEN           // Save/Restore LCD Contents

  #include <tigcclib.h>         // Include All Header Files

  int addition (int x1, int x2) {
    return (x1 + x2);
  }

  int multiplication (int x1, int x2) {
    return (x1 * x2);
  }

  // Main Function
  void _main(void)
  {
    int aux;

    clrscr();

    aux = addition (13, 8);
    printf ("13 + 8 = %d\n\n17 * 2 = %d", aux, multiplication(17, 2));

    ngetchx();
  }

 

5) The recursivity

        The recursivity seems like the loops but it is made by procedures or functions. In fact, within the code of your procedure, you call the same procedure: it is the same effect than with a simple loop. The advantage is your code is smaller but the disadvantages are: firstly the compiler stores all the calls and consequently it is less fast than a simple loop and secondly it is more complex to understand. But sometimes, you have less problems with recursivity. We can see two examples: one to understand how it works and another to see the efficiency in a real example.

Example 1:


                         


  // C Source File
  // Created 16/03/2003; 14:39:25

  #define USE_TI89              // Compile for TI-89
  #define USE_TI92PLUS          // Compile for TI-92 Plus
  #define USE_V200              // Compile for V200

  #define OPTIMIZE_ROM_CALLS    // Use ROM Call Optimization

  #define MIN_AMS 100           // Compile for AMS 1.00 or higher

  #define SAVE_SCREEN           // Save/Restore LCD Contents

  #include <tigcclib.h>         // Include All Header Files

  #define number              7 
    /*
    you must be careful because number < 13 or else the result is huge and over an unsigned long int 
    factorial (n) = n! = n*(n-1)*(n-2)*...*3*3*1 and 0! = 1
    example: 5! = 5*4*3*2*1 = 120
    */

  unsigned long factorial1 (int n) {
    int a;
    unsigned long facto;

    if (n == 0)
      return(1);

    facto = 1;
    for (a = 2; a <= n; a++)
      facto *= a;
    return (facto);
  }

  unsigned long factorial2 (int n) {
    if (n == 0)
      return (1);

    if (n != 1)
      return (n * factorial2 (n - 1));
    else
      return (1);
  }


  // Main Function
  void _main(void)
  {
    clrscr();

    printf ("13! = %lu\n", factorial1(number));
    printf ("13! = %lu", factorial2(number));

    ngetchx();
  }


Example 2:
        This example explains how you can make a menu and it is for me the simplest because if you do not use the recursivity, you will use an amount of conditions with several loops and you get the same effect because the speed is not important for a menu.


                         


  // C Source File
  // Created 16/03/2003; 15:10:58

  #define USE_TI89              // Compile for TI-89
  #define USE_TI92PLUS          // Compile for TI-92 Plus
  #define USE_V200              // Compile for V200

  #define OPTIMIZE_ROM_CALLS    // Use ROM Call Optimization

  #define MIN_AMS 100           // Compile for AMS 1.00 or higher

  #define SAVE_SCREEN           // Save/Restore LCD Contents

  #include <tigcclib.h>         // Include All Header Files

  // I declare the procedure because I call procedures within procedure 
  // and so I don't need to sort the procedures.

  char menu();

  void about();

  void options();

  void speed();

  void difficulty();

  // The procedures:

  /*
  The function 'menu' returns a char because I use the result like a boolean value.
  1 = true
  0 = false
  I use a char because it's not the worth to use an integer or a short. The compiler will use more
  memory storage and it's unuseful. Even a char takes much memory to store only 1 or 0!
  */

  char menu() {
    int key;

    clrscr();

    printf("F1 - Game\n\n");
    printf("F2 - Options\n\n");
    printf("F3 - About ...\n\n");
    printf("F4 - Exit");

    key = ngetchx();

    switch (key) {
      case KEY_F1:
        return (1);
        break;
      case KEY_F2:
        options();
        break;
      case KEY_F3:
        about();
        break;
      case KEY_F4:
      case KEY_ESC:
        return (0);
    }

    return (menu());
  }

  void about() {
    clrscr();

    printf ("This menu is created by:\n\n\n    Frédéric RIVAL\n\nMember of the Quiche Team");
    ngetchx();
  }

  void options() {
    int key;

    clrscr();
    printf("F1 - Dificulty\n\n");
    printf("F2 - Speed\n\n");
    printf("F3 - Return");

    key = ngetchx();

    switch (key) {
      case KEY_F1:
        difficulty();
        break;
      case KEY_F2:
        speed();
        break;
      case KEY_F3:
      case KEY_ESC:
        return;
    }

    options();
  }

  void speed() {
    clrscr();
    printf("Choose your speed");
    ngetchx();
  }

  void difficulty() {
    clrscr();
    printf("Choose your difficulty");
    ngetchx();
  }

  // Main Function
  void _main(void)
  {
    while (menu()) {
      clrscr();
      printf("Here the game!");
      ngetchx();
    }
  }

 





See another lesson
Retour au menu