.NOT. Logical NOT

.NOT.
 Logical NOT--unary                              (Logical)

 Syntax

     ! <lCondition>
     .NOT. <lCondition>

 Type

     Logical

 Operands

     <lCondition> is a logical expression to not.

 Description

     The not (!) operator is a unary logical operator that returns the
     logical inverse of <lCondition>.

 Examples

     .  This example shows .NOT. results using different operands:

        ? ! (.T.)               // Result: .F.
        ? ! 1 > 2               // Result: .T.
        ? .NOT. 1 > 2           // Result: .T.

See Also: .AND. .OR.

 

Introduction Number and Bit Manipulation

Introduction CT Number and Bit Manipulation

This module discusses number and bit manipulation. Specifically, the numeric section deals with conversions between two different number systems, and the creation of random numbers.

The bit manipulation section covers such required binary operations as AND, OR, XOR, and NOT, and how to test, set and clear bits. The NUMLOW() and NUMHIGH() functions are important for CA-Clipper Tools functions that take two 8-bit values and return them as combined 16-bit numbers. An example is the GETCURSOR() function from the Extended Drivers module.

Many of the functions in this module have a <value> parameter type. In this case, a number can be in the range of 0 to 65535 (or 4 294 967 295) and/or a hexadecimal string in the range of “0000” to “FFFF” (or “FFFFFFFF”).

CT Number and Bit Manipulation Functions

 

Hash vs Table

Consider a table for customers records with two character fields : Customer ID and customer name:

Cust_ID Cust_Name
CC001 Pierce Firth
CC002 Stellan Taylor
CC003 Chris Cherry
CC004 Amanda Baranski

 It’s known all possible and necessary operations on a table: APPEND, DELETE, SEEK and so on; by the way, for SEEK we need an index file also.

Listing this table is quite simple:

USE CUSTOMER
WHILE .NOT. EOF()
   ? CUST_ID, CUST_NAME
   DBSKIP()
ENDDO

 If our table is sufficiently small, we can find a customer record without index and SEEK :

LOCATE FOR CUST_ID = “CC003”
? CUST_ID, CUST_NAME

If we want all our data will stand in memory and we could manage it more simple and quick way, we would use an array ( with some considerations about size of table; if it is too big, this method will be problematic ) :

aCustomer := {}    // Declare / define an empty array
USE CUSTOMER
WHILE .NOT. EOF()
   AADD(aCustomer, { CUST_ID, CUST_NAME } )
   DBSKIP()
ENDDO
Traversing this array is quite simple :

FOR nRecord := 1 TO LEN( aCustomer )

    ? aCustomer[ nRecord, 1 ], aCustomer[ nRecord, 2 ]
NEXT
or :

a1Record := {}

FOR EACH a1Record IN aCustomer
   ? a1Record[ 1 ], a1Record[ 2 ]
NEXT

And locating a specific record too:

nRecord := ASCAN( aCustomer, { | a1Record | a1Record[ 1 ] == “CC003” } )

? aCustomer[ nRecord, 1 ], aCustomer[ nRecord, 2 ]

A lot of array functions are ready to use for maintain this array : ADEL(), AADD(), AINS() etc …

Now, let’s see how we could use a hash for achieve this job :

hCustomer := { => } // Declare / define an empty hash

USE CUSTOMER
WHILE .NOT. EOF()
   hCustomer[ CUST_ID ] := CUST_NAME
   DBSKIP()
ENDDO
Let’s traversing :

h1Record := NIL

FOR EACH h1Record IN hCustomer
   ? h1Record: __ENUMKEY(),h1Record:__ENUMVALUE()
NEXT

Now, we have a bit complicate our job; a few field addition to the table :

No: Field Name Type Width  Dec Decription

1

 CUST_ID

C

 5

0

Id ( Code )

2

 CUST_NAME

C

10

0

Name

3

 CUST_SNAM

C

10

0

Surname

4

 CUST_FDAT

D

 8

0

First date

5

 CUST_ACTV

L

 1

0

Is active ?

6

 CUST_BLNCE

N

11

2

Balance

 While <key> part of an element of a hash may be C / D / N / L type; <xValue> part of hash too may be ANY type of data, exactly same as arrays.

So, we can make fields values other than first ( ID) elements of an array:

hCustomer := { => } // Declare / define an empty hash
USE CUSTOMER
WHILE .NOT. EOF()
   a1Data:= { CUST_NAME, CUST_SNAM, CUST_FDAT, CUST_ACTV, CUST_BLNCE }
   hCustomer[ CUST_ID ] := a1Data
   DBSKIP()
ENDDO
Let’s traversing :

h1Record := NIL

FOR EACH h1Record IN hCustomer
   a1Key  := h1Record:__ENUMKEY()
   a1Data := h1Record:__ENUMVALUE()
   ? a1Key
   AEVAL( a1Data, { | x1 | QQOUT( x1 ) } )
NEXT
*-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._
/*
Hash vs Tables
 
*/
#define NTrim( n ) LTRIM( STR( n ) )
#define cLMarj SPACE( 3 )
PROCEDURE Main()

  SET DATE GERM
  SET CENT ON
  SET COLO TO "W/B"
  SetMode( 40, 120 )
 
  CLS
 
  hCustomers := { => } // Declare / define an empty PRIVATE hash
 
  IF MakUseTable() 
 
     Table2Hash()
 
     * Here the hash hCustomers may be altered in any way
 
     ZAP
 
     Hash2Table()
 
  ELSE
      ? "Couldn't make / USE table"
  ENDIF
 
  ?
  @ MAXROW(), 0
  WAIT "EOF HashVsTable.prg"
 
RETURN // HashVsTable.Main()
*-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.
PROCEDURE Table2Hash()
   hCustomers := { => } 
   WHILE .NOT. EOF()
     hCustomers[ CUST_ID ] := CUST_SNAM
     DBSKIP()
   ENDDO
 
   ListHash( hCustomers, "A hash transferred from a table (single value)" )
 
   hCustomers := { => } // Declare / define an empty hash
   DBGOTOP()
   WHILE .NOT. EOF()
      hCustomers[ CUST_ID ] := { CUST_NAME, CUST_SNAM, CUST_FDAT, CUST_ACTV, CUST_BLNCE }
      DBSKIP()
   ENDDO
 
   ListHash( hCustomers, "A hash transferred from a table (multiple values)" )
 
RETURN // Table2Hash()

*-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.

PROCEDURE Hash2Table()
   LOCAL h1Record,;
         c1Key,;
         a1Record,;
         n1Field
 
   FOR EACH h1Record IN hCustomers
      c1Key := h1Record:__ENUMKEY()
      a1Record := h1Record:__ENUMVALUE()
      DBAPPEND()
      FIELDPUT( 1, c1Key )
      AEVAL( a1Record, { | x1, n1 | FIELDPUT( n1 + 1 , x1 ) } )
   NEXT h1Record
   DBGOTOP()
 
   ?
   ? "Data trasferred from hash to table :"
   ?
   WHILE ! EOF()
      ? STR( RECN(), 5), ''
      FOR n1Field := 1 TO FCOUNT()
         ?? FIELDGET( n1Field ), ''
      NEXT n1Field
      DBSKIP()
   ENDDO 
 
RETURN // Hash2Table()

*-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.

PROCEDURE ListHash( hHash, cComment )
 
  LOCAL x1Pair
 
  cComment := IF( HB_ISNIL( cComment ), '', cComment )
 
  ? 
  ? cComment // , "-- Type :", VALTYPE( hHash ), "size:", LEN( hHash )
  ?
  IF HB_ISHASH( hHash ) 
     FOR EACH x1Pair IN hHash
        nIndex := x1Pair:__ENUMINDEX()
        x1Key := x1Pair:__ENUMKEY()
        x1Value := x1Pair:__ENUMVALUE()
        ? cLMarj, NTrim( nIndex ) 
*       ?? '', VALTYPE( x1Pair )
        ?? '', x1Key, "=>"
*       ?? '', VALTYPE( x1Key ) 
*       ?? VALTYPE( x1Value ) 
        IF HB_ISARRAY( x1Value ) 
           AEVAL( x1Value, { | x1 | QQOUT( '', x1 ) } )
        ELSE 
           ?? '', x1Value
        ENDIF 
     NEXT
  ELSE
    ? "Data type error; Expected hash, came", VALTYPE( hHash ) 
  ENDIF HB_ISHASH( hHash )
RETURN // ListHash()
*-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.

FUNCTION MakUseTable() // Make / USE table
 
 LOCAL cTablName := "CUSTOMER.DBF"
 LOCAL lRetval, aStru, aData, a1Record 
 
 IF FILE( cTablName ) 
    USE (cTablName)
 ELSE
    aStru := { { "CUST_ID", "C", 5, 0 },;
               { "CUST_NAME", "C", 10, 0 },;
               { "CUST_SNAM", "C", 10, 0 },;
               { "CUST_FDAT", "D", 8, 0 },;
               { "CUST_ACTV", "L", 1, 0 },;
               { "CUST_BLNCE", "N", 11, 2 } }
    * 
    * 5-th parameter of DBCREATE() is alias - 
    * if not given then WA is open without alias 
    *                              ^^^^^^^^^^^^^ 
    DBCREATE( cTablName, aStru, , .F., "CUSTOMER" ) 
 
    aData := { { "CC001", "Pierce", "Firth", 0d20120131, .T., 150.00 },; 
               { "CC002", "Stellan", "Taylor", 0d20050505, .T., 0.15 },;
               { "CC003", "Chris", "Cherry", 0d19950302, .F., 0 },;
               { "CC004", "Amanda", "Baranski", 0d20011112, .T., 12345.00 } }
 
    FOR EACH a1Record IN aData
        CUSTOMER->(DBAPPEND())
        AEVAL( a1Record, { | x1, nI1 | FIELDPUT( nI1, X1 ) } )
    NEXT a1Record 
    DBGOTOP()
 
 ENDIF 
 
 lRetval := ( ALIAS() == "CUSTOMER" )
 
RETURN lRetval // MakUseTable()

*-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._
 
HashVsTable