SWITCH

SWITCH

Executes one or more blocks of statements.

Syntax

       SWITCH SwitchExp
          CASE LiteralExp1
            ...
            [EXIT]
         [CASE LiteralExp2]
            ...
            [EXIT]
         [CASE LiteralExpn]
            ...
            [EXIT]
         OTHERWISE
                ...
       END [SWITCH]

Arguments

The <LiteralExp> must be a compiled time resolvable numeric or character expression, and may involve operators, as long as such operators involve compile time static value.

CASE <LiteralExp1> .. <LiteralExp> is a constant value of the same data type as <SwitchExp>.

The EXIT optional statement is the equivalent of the C statement break, and if present, execution of the SWITCH structure will end when the EXIT statement is reached, otherwise it will continue with the first statement below the next CASE statement (fall through)

Description

SWITCH is a Harbour construct inspired by the C implementation of switch().

The SWITCH statement compares a constant value against a series of constant values. It is similar to the DO CASE statement but outperforms it to a great extent due to the restrictions introduced with values permitted for comparison. As a general rule, only literal values in form integer or character constants may follow the CASE clauses.

The SWITCH statement evaluates <SwitchExp> and then searches for a first match between the resulting value and <LiteralExp>. When a match is found, the statements following the corresponding CASE clause are executed down to the END statement. To suppress execution of statements of the next CASE clause, the EXIT statement must be explicitely used. This is a major difference to the DO CASE statement where subsequent CASE clauses are skipped once a first match is found.

If no initial match is found with the CASE clauses, the statements following OTHERWISE are executed, if present.

Example

        // The example demonstrates the SWITCH control structure
        // Try with and without EXIT statements
        PROC Main()
           LOCAL cSName := "Doe"
           SWITCH cSName

              CASE "Abba"
                 ? "Abaneoer"
                 EXIT

              CASE "Bo"
                 ? "Boeing"
                 EXIT
              CASE "Doe"
                 ? "John"
                 EXIT

              OTHERWISE
                 ? "Guest"
           END

            ?? '', cSName
           ?
           WAIT "EOF SwitchTest.prg"
        RETU

Seealso

DO CASE, IF…ELSEIF…ENDIF

IF

IF

Execute one of several alternative blocks of statements

Syntax

       IF <lCondition1>
          <statements>...
       [ELSEIF <lCondition2>]
          <statements>...
       [ELSE]
          <statements>...
       END[IF]

Arguments

<lCondition> is a logical control expression. If it evaluates to true (.T.), all following statements are executed until an ELSEIF, ELSE, or ENDIF is encountered.

ELSEIF <lCondition> identifies statements to execute if the associated condition evaluates to true (.T.) and all preceding IF or ELSEIF conditions evaluate to false (.F.). Any number of ELSEIF statements can be specified within the same IF…ENDIF control structure.

ELSE identifies statements to execute if the IF and all preceding ELSEIF conditions evaluate to false (.F.).

Description

The IF control structure works by branching execution to statements following the first true (.T.) evaluation of the IF or any ELSEIF condition. Execution then continues until the next ELSEIF, ELSE, or ENDIF is encountered whereupon execution branches to the first statement following the ENDIF.

If no condition evaluates to true (.T.), control passes to the first statement following the ELSE statement. If an ELSE statement is not specified, control branches to the first statement following the ENDIF statement.

IF…ENDIF structures may be nested within IF…ENDIF structures and other control structure commands. These structures, however, must be nested properly. The IF…ELSEIF…ENDIF form of the IF construct is identical to DO CASE…ENDCASE. There is no specific advantage of one syntax over the other.

The IF construct is also similar to the IF() function which can be used within expressions.

Examples

       .  This example evaluates a number of conditions using an
       IF...ELSEIF...ENDIF construct:
       LOCAL nNumber := 0
       //
       IF nNumber < 50
          ? "Less than 50"
       ELSEIF nNumber = 50
          ? "Is equal to 50"
       ELSE
          ? "Greater than 50"
       ENDIF

Seealso

BEGIN SEQUENCE, DO CASE, DO WHILE, FOR, IF()

FOR…NEXT

FOR…NEXT

Execute a block of statements a specified number of times

Syntax

       FOR <idCounter> := <nStart> TO <nEnd> [STEP <nIncrement>]
           <statements>...
           [EXIT]
           <statements>...
           [LOOP]
       NEXT

Arguments

<idCounter> is the name of the loop control or counter variable. If the specified <idCounter> is not visible or does not exist, a private variable is created.

<nStart> is the initial value assigned to <idCounter>. If <nIncrement> is negative, <nStart> must be less than <nEnd>.

TO <nEnd> defines the final value of <idCounter>. If <nIncrement> is negative, <nStart> must be greater than <nEnd>; otherwise, <nStart> must be less than <nEnd>.

STEP <nIncrement> defines the amount <idCounter> is changed for each iteration of the loop. <nIncrement> can be either positive or negative. If the STEP clause is not specified, <idCounter> is incremented by one for each iteration of the loop.

EXIT unconditionally branches control from within a FOR…NEXT construct to the statement immediately following the nearest NEXT statement.

LOOP branches control to the most recently executed FOR or DO WHILE statement.

Description

FOR…NEXT is a control structure that executes a block of statements a specified number of times. The control structure loops from the initial value of <idCounter> to the boundary specified by <nEnd>, moving through the range of values of the control variable for an increment specified by <nIncrement>. All expressions in the FOR statement are reevaluated for each iteration of the loop. The <nStart> and <nEnd> expressions, therefore, can be changed as the control structure operates.

A FOR loop operates until <idCounter> is greater than <nEnd> or an EXIT statement is encountered. Control then branches to the statement following the corresponding NEXT statement. If a LOOP statement is encountered, control branches back to the current FOR statement.

If <nIncrement> is a negative value, <idCounter> is decremented rather than incremented. The FOR loop, however, continues until <idCounter> is less than <nEnd>. This means that <nEnd> must be less than <nStart> when the FOR loop begins.

FOR loops are useful for traversing arrays where <idCounter> is used as the array subscript. See the example below.

FOR…NEXT constructs may be nested within any other control structures to any depth. The only requirement is that each control structure is properly nested.

Examples

       .  This example traverses an array in ascending order:
       nLenArray := LEN(aArray)
       FOR i := 1 TO nLenArray
           <statements>...
       NEXT
       .  To traverse an array in descending order:
       nLenArray := LEN(aArray)
       FOR i := nLenArray TO 1 STEP -1
          <statements>...
       NEXT

Seealso

AEVAL(), BEGIN SEQUENCE, DO CASE, DO WHILE, IF, IF()

SP_AASKIP

AASKIP()

  Short:
  ------
  AASKIP() Use for skipblock for arrays in Tbrowse

  Returns:
  --------
  <nSkipcount> => number skipped, forward or backward

  Syntax:
  -------
  AASKIP(nSkip,@nElement,nMaxRows)

  Description:
  ------------
  Use this to create the SKIPBLOCK for a tbrowse that browses
  an array, as in :

    aTbrowseObject:SKIPBLOCK := {|n|aaskip(n,@nElement,len(aArray)}

  <nSkip>      is passed in by Tbrowse as a +- value, or
               as zero.

  <nElement>   is the current array element number.
               PASSED IN BY REFERENCE!

  <nMaxrows>   refers to the length of the array being
               browsed

  Examples:
  ---------
  // this example browses the fields in a database

   local nLastKey,  nElement    := 1
   local aArray := dbstruct()
   local oTb        := tBrowseNew(2,2,20,78)
   oTb:addcolumn(tbcolumnew("Name",{||aArray[nElement,1]}))
   oTb:addcolumn(tbcolumnew("Type", {||aArray[nElement,2]}))
   oTb:addcolumn(tbcolumnew("Len " , {||aArray[nElement,3]}))
   oTb:addcolumn(tbcolumnew("Deci",  {||aArray[nElement,4]}))
   oTb:Skipblock        := {|n|aaskip(n,@nElement,len(aArray)}
   oTb:goTopBlock       := {||nElement := 1}
   oTb:goBottomBlock    := {||nElement := len(aArray)}

   while .t.
     while !oTb:stabilize()
     end
     nLastKey := inkey(0)
     do case
        /// various actions.....
     endcase
   end

  Notes:
  -------
  Aaskip() is used by a lot of SuperLib functions, but
  is very useful by itself for creating array tbrowses.

  Source:
  -------
  S_AASKIP.PRG

 

 

TBrowse & TBColumn basics

TBrowse and TBColumn basics (.pdf)

Working version of sample program in this article.

 

TBr_Bass

Using code blocks, again

Using code blocks again (.pdf)

C5 Flow Control Commands, Statements and Funtions

Commands :

CALL* :

Execute a C or Assembler procedure

CALL <idProcedure> [WITH <exp list>]

CANCEL* :

Terminate program processing

CANCEL* | QUIT

DO* :

Call a procedure

DO <idProcedure> [WITH <argument list>]

QUIT

Terminate program processing

QUIT | CANCEL*

RUN :

Execute a DOS command or program

RUN | !* <xcCommandLine>

SET KEY :

Assign a procedure invocation to a key

SET KEY <nInkeyCode> TO [<idProcedure>]

SET PROCEDURE *:

Compile procedures/functions into the current .OBJ file

SET PROCEDURE TO [<idProgramFile>[.<ext>]]

WAIT* :

Suspend program processing until a key is pressed

WAIT [<expPrompt>] [TO <idVar>]

Statements :

ANNOUNCE :

Declare a module identifier

ANNOUNCE <idModule>

 BEGIN SEQUENCE :

Define a sequence of statements for a BREAK

BEGIN SEQUENCE
       <statements>...
    [BREAK [<exp>]]
       <statements>...
    [RECOVER [USING <idVar>]]
       <statements>...
END [SEQUENCE]

DO CASE :

Execute one of several alternative blocks of statements

DO CASE
   CASE <lCondition1>
       <statements>...
   [CASE <lCondition2>]
       <statements>...
   [OTHERWISE]
       <statements>...
END[CASE]

DO WHILE :

Execute a loop while a condition is true (.T.)

[DO] WHILE <lCondition>
    <statements>...
    [EXIT]
    <statements>...
    [LOOP]
    <statements>...
END[DO]

EXIT PROCEDURE :

Declare an exit procedure

EXIT PROCEDURE <idProcedure>
    [FIELD <idField list> [IN <idAlias>]]
    [LOCAL <identifier> [[:= <initializer>]]]
    [MEMVAR <identifer list>]
    .
    . <executable statements>
    .
[RETURN]

EXTERNAL* :

Declare a list of procedure or user-defined function names

EXTERNAL <idProcedure list>

FOR :

Execute a block of statements a specified number of times

FOR <idCounter> := <nStart> TO <nEnd> [STEP <nIncrement>]
    <statements>...
    [EXIT]
    <statements>...
    [LOOP]
NEXT

FUNCTION :

Declare a user-defined function name and formal parameters

[STATIC] FUNCTION <idFunction>[(<idParam list>)]
    [LOCAL <identifier> [[:= <initializer>], ... ]]
    [STATIC <identifier> [[:= <initializer>], ... ]]
    [FIELD <identifier list> [IN <idAlias>]]
    [MEMVAR <identifier list>]
    .
    . <executable statements>
    .
RETURN <exp>

IF :

Execute one of several alternative blocks of statements

IF <lCondition1>
    <statements>...
[ELSEIF <lCondition2>]
    <statements>...
[ELSE]
    <statements>...
END[IF]

INIT PROCEDURE :

Declare an initialization procedure

INIT PROCEDURE <idProcedure> [(<idParam list>)]
    [FIELD <idField list> [IN <idAlias>]]
    [LOCAL <identifier> [[:= <initializer>]]]
    [MEMVAR <identifer list>]
    .
    . <executable statements>
    .
[RETURN]

NOTE :

Place a single-line comment in a program file

NOTE This is a comment line

PARAMETERS :

Create private parameter variables

PARAMETERS <idPrivate list>

PROCEDURE :

Declare a procedure name and formal parameters

[STATIC] PROCEDURE <idProcedure> [(<idParam list>)]
    [FIELD <idField list> [IN <idAlias>]
    [LOCAL <identifier> [[:= <initializer>], ... ]]
    [MEMVAR <identifier list>]
    [STATIC <identifier> [[:= <initializer>], ... ]]
    .
    . <executable statements>
    .
[RETURN]

REQUEST :

Declare a module request list

REQUEST <idModule list>

RETURN :

Terminate a procedure, user-defined function or program

RETURN [<exp>]

Functions :

BREAK() :

Branch out of a BEGIN SEQUENCE…END construct

BREAK(<exp>) --> NIL

EVAL() :

Evaluate a code block

EVAL(<bBlock>, [<BlockArg list>]) --> LastBlockValue

IF() :

Return the result of an expression based on a condition

[I]IF(<lCondition>, <expTrue>, <expFalse>) --> Value

PCOUNT() :

Determine the position of the last actual parameter passed

PCOUNT() --> nLastArgumentPos

SETKEY() :

Assign an action block to a key

SETKEY(<nInkeyCode>, [<bAction>]) --> bCurrentAction

SETCANCEL() :

Toggle Alt-C and Ctrl-Break as program termination keys

SETCANCEL([<lToggle>]) --> lCurrentSetting

WORD()* :

Convert CALL command numeric parameters from double to int

WORD(<nNumber>) --> NIL

DO CASE..ENDCASE

Control Structures – Decision making; DO CASE..ENDCASE

Do Case

/*

Control Structures - Decision making; DO CASE..ENDCASE

For more information refer here 

*/

PROCEDURE Main()
   CLS

   nKey := 0

   cDash := ''

   ? "Press a digit key ( Esc for exit ) : " 

   DO WHILE nKey # 27

      nKey := INKEY( 0 )

      IF nKey > 47 .AND. nKey < 58 

         ?? cDash

         DO CASE
            CASE nKey = 48
               ?? "zero"
            CASE nKey = 49
               ?? "one"
            CASE nKey = 50
               ?? "two"
            CASE nKey = 51
               ?? "three"
            CASE nKey = 52
               ?? "four"
            CASE nKey = 53
               ?? "five"
            CASE nKey = 54
               ?? "six"
            CASE nKey = 55
               ?? "seven"
            CASE nKey = 56
               ?? "eight"
            CASE nKey = 57
               ?? "nine"
         ENDCASE

         cDash := '-'

      ENDIF nKey > 47 .AND. nKey > 58 

   ENDDO

RETURN // Main()