# .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.```

# 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"

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 } }

CUSTOMER->(DBAPPEND())
AEVAL( a1Record, { | x1, nI1 | FIELDPUT( nI1, X1 ) } )
NEXT a1Record
DBGOTOP()

ENDIF

lRetval := ( ALIAS() == "CUSTOMER" )

RETURN lRetval // MakUseTable()

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

```