Basic Programming Concepts

When you program, you store data and manipulate it with a series of instructions. The data and data storage containers are the raw materials of programming. The tools you use to manipulate this raw material are commands, functions, and operators.

Storing Data

The data you work with probably includes amounts of time, money, and countable items, as well as dates, names, descriptions, and so on. Each piece of data is a certain type: it belongs to a category of data that you manipulate in similar ways. You could work directly with this data without storing it, but you would lose most of the flexibility and power of Visual FoxPro. Visual FoxPro provides numerous storage containers to extend your ability to easily manipulate data.

Data types determine how data is stored and how it can be used. You can multiply two numbers together, but you can't multiply characters. You can print characters in uppercase, but you can't print numbers in uppercase. Some of the primary data types in Visual FoxPro are listed in the following table:

Data Types

Type Examples
Numeric 123
3.1415
– 7
Character "Test String"
"123"
"01/01/98"
Logical .T.
.F.
Date

DateTime

{^1998-01-01}

{^1998-01-01 12:30:00 p}

Data Containers

Data containers allow you to perform the same operations on multiple pieces of data. For example, you add the hours an employee has worked, multiply them by the hourly wage, and then deduct the taxes to determine the amount of pay the employee has earned. You'll have to perform these operations for every employee and every pay period. If you store this information in containers, and perform the operations on the containers, you can just replace the old data with new data and run the same program again. This table lists some of the main containers for data in Visual FoxPro:

Type Description
Variables Single elements of data stored in your computer's RAM (Random Access Memory).
Table Records Multiple rows of predetermined fields, each of which can contain a predefined piece of data. Tables are saved to disk.
Arrays Multiple elements of data stored in RAM.

Manipulating Data

Containers and data types give you the building blocks you need to manipulate data. The final pieces are operators, functions, and commands.

Using Operators

Operators tie data together. Here are the most common operators in Visual FoxPro.

Operator Valid Data Types Example Result
= All
? n = 7
Prints .T. if the value stored in the variable n is 7, .F. otherwise
+ Numeric, Character, Date, DateTime
? "Fox" + "Pro"
Prints "FoxPro"
! or NOT Logical
? !.T.
Prints .F.
*, / Numeric
? 5 * 5
? 25 / 5
Prints 25
Prints 5

Note   A question mark (?) in front of an expression causes a new line character and the results of the expression to be printed in the active output window, which is usually the main Visual FoxPro window.

Remember that you must use the same type of data with any one operator. The following statements store two numeric pieces of data to two variables. The variables have been given names that start with n so we can tell at a glance that they contain numeric data, but you could name them with any combination of alphanumeric characters and underscores.

nFirst = 123
nSecond = 45

The following statements store two pieces of character data to two variables. The variables have been given names that start with c to indicate that they contain character data.

cFirst = "123"
cSecond = "45"

The following two operations, addition and concatenation, yield different results because the type of data in the variables is different.

? nFirst + nSecond
? cFirst + cSecond

Output

168
12345

Because cFirst is character data and nSecond is numeric data, you get a data type mismatch error if you try the following command:

? cFirst + nSecond

You can avoid this problem by using conversion functions. For example, STR( ) returns the character equivalent of a numeric value and VAL( ) returns the numeric equivalent of a character string of numbers. These functions and LTRIM( ), which removes leading spaces, enable you to perform the following operations:

? cFirst + LTRIM(STR(nSecond))
? VAL(cFirst) + nSecond

Output

12345
168

Using Functions

Functions return a specific type of data. For example, the functions STR( ) and VAL( ), used in the previous section, return character and numeric values, respectively. As with all functions, these return types are documented along with the functions.

There are five ways to call a Visual FoxPro function:

  • Assign the return value of the function to a variable. The following line of code stores the current system date to a variable named dToday:

    dToday = DATE( )
    
  • Include the function call in a Visual FoxPro command. The following command sets the default directory to the value returned from the GETDIR( ) function:

    CD GETDIR( )
    
  • Print the return value in the active output window. The following line of code prints the current system time in the active output window:

    ? TIME( )
    
  • Call the function without storing the return value anywhere. The following function call turns the cursor off:

    SYS(2002)
    
  • Embed the function in another function. The following line of code prints the day of the week:

    ? DOW(DATE( ))
    

Some other examples of functions used in this section are:

Function Description
ISDIGIT( ) Returns true (.T.) if the leftmost character in a string is a number; otherwise, returns false (.F.).
FIELD( ) Returns the name of a field.
LEN( ) Returns the number of characters in a character expression.
RECCOUNT( ) Returns the number of records in the currently active table.
SUBSTR( ) Returns the specified number of characters from a character string, starting at a specified location in the string.

Using Commands

A command causes a certain action to be performed. Each command has a specific syntax, which indicates what must be included in order for the command to work. There are also optional clauses associated with commands that allow you to specify in more detail what you want.

For example, the USE command allows you to open and close tables:

USE Syntax Description
USE
Closes the table in the current work area.
USE customer
Opens the CUSTOMER table in the current work area, closing any table that was already open in the work area.
USE customer IN 0
Opens the CUSTOMER table in the next available work area.
USE customer IN 0 ;
  ALIAS mycust
Opens the CUSTOMER table in the next available work area and assigns the work area an alias of mycust.

Some examples of commands used in this section are:

Command Description
DELETE Marks specified records in a table for deletion.
REPLACE Replaces the value stored in record field with a new value.
Go Positions the record pointer to a specific location in the table.

Controlling Program Flow

Visual FoxPro includes a special category of commands that "wrap around" other commands and functions, determining when and how often the other commands and functions are executed. These commands allow conditional branching and looping, two very powerful programming tools. The following program illustrates conditional branches and loops. These concepts are described in more detail after the example.

Suppose that you had 10,000 employees and wanted to give everybody making $30,000 or more a 3 percent raise, and everybody making under $30,000 a 6 percent raise. The following sample program accomplishes this task.

This program assumes that a table with a numeric field named salary is open in the current work area. For information about work areas, see "Using Multiple Tables" in Working with Tables.

Sample Program to Increase Employee Salaries

Code Comments
SCAN
The code between SCAN and ENDSCAN is executed as many times as there are records in the table. Each time the code is executed, the record pointer moves to the next record in the table.
   IF salary >= 30000.00
      REPLACE salary WITH ;
         salary * 1.03
For each record, if the salary is greater than or equal to 30,000, replace this value with a new salary that is 3% higher.

The semicolon (;) after WITH indicates that the command is continued on the next line.

   ELSE
      REPLACE salary WITH ;
         salary * 1.06
For each record, if the salary is not greater than or equal to 30,000, replace this value with a new salary that is 6% higher.
   ENDIF
ENDSCAN
End of the conditional IF statement.

End of the code that is executed for each record in the table.

This example uses both conditional branching and looping commands to control the flow of the program.

Conditional Branching

Conditional branching allows you to test conditions and then, depending on the results of that test, perform different operations. There are two commands in Visual FoxPro that allow conditional branching:

The code between the initial statement and the ENDIF or ENDCASE statement is executed only if a logical condition evaluates to true (.T.). In the example program, the IF command is used to distinguish between two states: either the salary is $30,000 or more, or it isn't. Different actions are taken depending on the state.

In the following example, if the value stored in the variable nWaterTemp is less than 100, no action is taken:

* set a logical variable to true if a condition is met.
IF nWaterTemp >= 100
   lBoiling = .T.
ENDIF

Note   An asterisk at the beginning of a line in a program indicates that the line is a comment. Comments help the programmer remember what each segment of code is designed to do, but are ignored by Visual FoxPro.

If there are several possible conditions to check for, a DO CASE ... ENDCASE block can be more efficient and easier to keep track of than multiple IF statements.

Looping

Looping allows you to execute one or more lines of code as many times as you need to. There are three commands in Visual FoxPro that allow looping:

Use SCAN when you are performing a series of actions for each record in a table, as in the example program just described. The SCAN loop enables you to write the code once and have it executed for each record as the record pointer moves through the table.

Use FOR when you know how many times the section of code needs to be executed. For example, you know there are a specific number of fields in a table. Because the Visual FoxPro function FCOUNT( ) returns this number, you can use a FOR loop to print the names of all the fields in the table:

FOR nCnt = 1 TO FCOUNT( )
   ? FIELD(nCnt)
ENDFOR

Use DO WHILE when you want to execute a section of code as long as a certain condition is met. You might not know how many times the code will have to execute, but you know when it should stop executing. For example, let's assume you have a table with people's names and initials, and you want to use the initials to look people up. You would have a problem the first time you tried to add a person who had the same initials as someone else already in your table.

To solve the problem, you could add a number to the initials. For example, Michael Suyama's identification code could be MS. The next person with the same initials, Margaret Sun, would be MS1. If you then added Michelle Smith to the table, her identification code would be MS2. A DO WHILE loop enables you to find the right number to append to the initials.

Sample Program with DO WHILE to Generate a Unique ID

Code Comments
nHere = RECNO()
Save the location of the record.
cInitials = LEFT(firstname,1) + ;
   LEFT(lastname,1)
nSuffix = 0
Get the person's initials from the first letters of the firstname and lastname fields.

Establish a variable to hold the number to be added to the end of a person's initials if necessary.

LOCATE FOR person_id = cInitials
See if there is another person in the table with the same initials.
DO WHILE FOUND( )
If another record in the table has a person_id value that is the same as cInitials, the FOUND( ) function returns true (.T.) and the code in the DO WHILE loop executes.
If no match is found, the next line of code to be executed is the line following ENDDO.
   nSuffix = nSuffix + 1
   cInitials = ;
      LEFT(cInitials,2);
      + ALLTRIM(STR(nSuffix))
Prepare a fresh suffix and append it to the end of the initials.
   CONTINUE
CONTINUE causes the last LOCATE command to be evaluated again. The program checks to see if the new value in cInitials already exists in the person_id field of another record. If so, FOUND( ) will still return .T. and the code in the DO WHILE loop will execute again. If the new value in cInitials is indeed unique, FOUND( ) will return .F. and program execution continues with the line of code following ENDDO.
ENDDO
End of the DO WHILE loop.
GOTO nHere
REPLACE person_id WITH cInitials
Return to the record and store the unique identification code in the person_id field.

Because you don't know beforehand how many times you'll find matching identification codes already in use, you use the DO WHILE loop.

See Also

Constructing a Small Program | Working with Tables | SCAN ... ENDSCAN | FOR ... ENDFOR | DO WHILE ... ENDDO | IF ... ELSE ... ENDIF | DO CASE ... ENDCASE | GETDIR( ) | USE