Using Functions


The main difference between procedures and functions is that functions have a return value. When you call a procedure in an application, the procedure executes and that's about it. When you call a function, the function executes and returns a value to the caller application.

Here is a simple function header:

function SomeFunction(ParameterList): ReturnValue;

Functions are more versatile than procedures. While procedures can only be called as standalone statements, functions can be called as standalone statements and can also be used in expressions.

Let's take a look at the Chr function that we used earlier. The Chr function can be used to convert an integer value to an ASCII character. The header of the Chr function looks like this:

function Chr(X: Byte): Char; 

The example in Listing 5-2 uses the Chr function to illustrate both function call methods.

Listing 5-2: Function calls

image from book
program Project1; {$APPTYPE CONSOLE} uses   SysUtils; var   c: Char; begin   { standalone call }   Chr(65);   { function call in an expression }   c := 'A';   if c = Chr(65) then     WriteLn('ASCII 65 = A');   ReadLn; end.
image from book

Note that calling functions as procedures (outside of an expression) defeats the very purpose of functions. When you call a function as you would a procedure, the return value of the function is discarded. The return value is usually the reason that you call a function in the first place, but there are situations in which you only need the function to execute without giving you a result. For instance, you can call a function that copies a file without needing to know how many bytes have actually been transferred.

There are three more standard functions that you can use in your application. All three functions are extremely fast and versatile. The first one is Ord, which can, for instance, be used to convert a character value to an integer.

The other two functions operate on all ordinal values and return the predecessor (the Pred function) or the successor (the Succ function) of a value. These functions are pretty special because Delphi doesn't even treat them as functions, instead computing their result at compile time. These functions can also be used in constant declarations.

const   X = Succ(19);  { 20 }   Y = Pred(101); { 100 }   Z = Ord('A');  { 65 }

Typecasting in Delphi

Typecasting is the process of converting a value or a variable from one data type to another. There are two types of typecasting: implicit and explicit. Explicit typecasting is also called conversion.

The difference between implicit and explicit typecasting is that implicit typecasting is lossless, whereas explicit typecasting can result in data loss. Implicit typecasting is only possible with compatible data types, usually only ordinal types. For instance, implicit typecasting is automatically done by Delphi when you assign an integer value to a Double variable.

var   i: Integer;   d: Double; begin   i := 2005;   d := i; end.

An automatic typecast is possible because a Double variable can hold larger values than an integer value. When you assign an integer value to a Double variable (or any other variable that can hold an integer value), the integer value is expanded and assigned to the destination variable.

If you have to perform an implicit typecast manually, the syntax is:

DataType(Expression)

We have already performed implicit typecasts earlier in this chapter, usually to convert character values to integers:

var   c: Char;   i: Integer; begin   c := 'X';   i := Integer(c); end.

If you try to assign a large value to a variable that cannot hold it, the compiler will give you the "Constant expression violates subrange bounds" or "Incompatible types: 'Type' and 'Type'" error. If you get one of these errors, you'll have to perform either an implicit or an explicit typecast.

var   b: Byte; begin   b := 255;        { OK }   b := 1000;       { Error, subrange bounds violation }   b := Byte(1000); { OK } end.

When you get a subrange bounds violation error, you should think about selecting another data type that supports larger values. What do you think the value of the variable will be after the implicit typecast to Byte(1000)? It can't be 1000 because the value 1000 occupies 2 bytes of memory, and a Byte variable occupies only 1 byte of memory. When we convert the number 1000 (hexadecimal 03E8) to a Byte value, the low-order byte (hexadecimal E8) is written to the Byte variable. The value of the Byte variable after the implicit typecast is 232.

Assigning a Double value to an integer variable also results in a compiler error because integer variables cannot hold real numbers. When you have to assign a real value to an integer, you always have to perform an explicit type- cast. You can convert a real value to an integer using either the Round or the Trunc standard functions. The Trunc function strips the decimal part of the number, and the Round function takes the decimal part of the number into account; they usually give different results. Round and Trunc can also be used in constant declarations.

var   i: Integer;   d: Double; begin   d := 12.8;   i := Round(d); { i = 13 }   i := Trunc(d); { i = 12 } end.

In Delphi, you can differentiate a constant value typecast and a variable type- cast. A value typecast is actually the implicit typecast we've used so far. A value typecast can only be written on the right side of the assignment statement.

A variable typecast can be written on both sides of the assignment statement, as long as both types are compatible.

Var   b: Byte;   c: Char; begin   b := Byte('a'); { value typecast }   c := Char(b);   { variable typecast }   Byte(c) := 65;  { temporary variable typecast } end.

Typecasting in C++

To typecast a variable in C++, you can use the standard Delphi syntax for an implicit typecast or the C++ syntax. Here are both:

(new_data_type)expression;

or

new_data_type(expression);

Here's how to perform both explicit and implicit typecasts in C++:

#include <iostream.h> #include <conio.h> #pragma hdrstop #pragma argsused int main(int argc, char* argv[]) {    /* note that the same syntax works for    implicit and explicit typecasts */    float f = 65.20;    char c = (char)f;    double d = 12.9;    int x = int(d);    cout << c << endl;   // writes "A"    cout << x << endl;   // writes "12"    getch();    return 0; }



Inside Delphi 2006
Inside Delphi 2006 (Wordware Delphi Developers Library)
ISBN: 1598220039
EAN: 2147483647
Year: 2004
Pages: 212
Authors: Ivan Hladni

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net