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 | {^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 |
|
Prints .T. if the value stored in the variable n is 7, .F. otherwise |
+ | Numeric, Character, Date, DateTime |
|
Prints "FoxPro" |
! or NOT |
Logical |
|
Prints .F. |
*, / | Numeric |
|
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 |
---|---|
|
Closes the table in the current work area. |
|
Opens the CUSTOMER table in the current work area, closing any table that was already open in the work area. |
|
Opens the CUSTOMER table in the next available work area. |
|
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 |
---|---|
|
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. |
|
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. |
|
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. |
|
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 |
---|---|
|
Save the location of the record. |
|
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. |
|
See if there is another person in the table with the same initials. |
|
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. |
|
Prepare a fresh suffix and append it to the end of the initials. |
|
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. |
|
End of the DO WHILE loop. |
|
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