« Назад
Реализуют ветвления IF … ENDIF, выбор DO CASE … ENDCASE и циклы DO WHILE … ENDDO, FOR EACH … ENDFOR и FOR … ENDFOR. Состоят из команд IF, ENDIF, DO CASE и т. д.
Конструкции могут быть вложенными. Каждая конструкция может содержать любую другую конструкцию.
Конструкция
IF lExpression [THEN] Commands ENDIF
выполняет команды Commands, если логическое выражение lExpression вычисляется со значением .T.
Конструкция
IF lExpression [THEN] Commands1 ELSE Commands2 ENDIF
выполняет команды Commands1, если логическое выражение lExpression вычисляется со значением .T., или выполняет команды Commands2 – в противном случае.
Пример. Выводятся все положительные элементы одномерного массива someArray, а также их общее количество. При отсутствии положительных элементов печатается соответствующее сообщение.
declare someArray[10]
&& Все элементы массива будут равны –2
store –2 to someArray
&& Теперь массив будет иметь 2 положительных элемента
someArray[2] = 1
someArray[5] = 3
numberOfPositiveElements = 0
for each element in someArray
&& Проверяем знак элемента массива
if element > 0 then
&& Элемент положителен. Увеличиваем numberOfPositiveElements
&& и печатаем значение элемента
numberOfPositiveElements = numberOfPositiveElements + 1
? element
endif
next
if numberOfPositiveElements > 0 then
? "Число положительных элементов в массиве someArray: ", ;
numberOfPositiveElements
else
? "В массиве someArray нет положительных элементов!"
endif
Функция
IIF(lExpression, eExpression1, eExpression2)
возвращает результат выражения eExpression1, если логическое выражение lExpression вычисляется со значением .T., или результат выражения eExpression2 – в противном случае. Также функция вернет результат выражения eExpression2, если lExpression вычисляется со значением . NULL.
Функцию следует использовать, если это возможно, взамен конструкции IF ... ENDIF. Особенно она полезна при работе с отчетами и этикетками.
Функции IIF( ) выполняется быстрее, чем эквивалентная конструкция IF ... ENDIF.
Пример 1. Заменяются отрицательные элементы массива на число –1, а положительные – на число 1.
declare someArray[10]
store –2 to someArray
someArray[2] = 1
someArray[5] = 3
someArray[9] = 0
for k = 1 to Alen(someArray)
if someArray[k] != 0 then
someArray[k] = Iif(someArray[k] > 0, 1, –1)
endif
next
&&
&& Контрольный вывод
for each element in someArray
?? element && Напечатает: –1 1 –1 –1 1 –1 –1 –1 0 –1
next
Пример 2 (приводится в справке VFP):
close databases
open database (Home(2) + 'Data\TestData')
use Employee
scan
&& Печатаем либо сообщение 'Описания нет!', либо содержимое поля Notes
? Iif(Empty(Notes), 'Описания нет!', Notes)
endScan
Конструкция
DO CASE CASE lExpression1 [Commands1] [CASE lExpression2 [Commands2]] ... [CASE lExpressionN [CommandsN]] [OTHERWISE [Commands]] ENDCASE
выполняет первый набор команд, для которого логическое выражение lExpression вычисляется со значением .T.
Так, первоначально оценивается выражение lExpression1 и если оно возвращает .T., то выполнятся команды Commands1 и управление будет передано оператору, следующему за командой ENDCASE. В противном случае, если lExpression1 – это .F., оценивается выражение lExpression2 и т. д.
Если все логические выражения lExpression вернут .F. и если имеется команда OTHERWISE, то будут выполнены команды Commands, следующие за этой командой.
Пример. Функция DoOperation( ) возвращает сумму, разность, произведение или частное двух своих первых параметров в зависимости от значения третьего параметра. Функция вернет .F., если третий параметр, задающий вид операции, имеет недопустимое значение.
op = '+' && или '–', или '*', или '/', , или '^', или ':'
a = 5
b = 2
x = DoOperation(a, b, op)
function DoOperation(a, b, op)
do case
case op == '+' or op == '–' or op == '*' or op == '/' or op == '^'
x = a &op b && Используем макроподстановку
case op == ':'
x = a / b
otherwise
x = .F.
endcase
return x
endFunc
Функция
ICASE(lCondition1, eResult1 [, lCondition2, eResult2] ... [, eOtherwiseResult])
оценивает логические выражения и возвращает один из возможных результатов. Число пар передаваемых функции параметров не должно быть более 100.
Параметры:
lCondition – оцениваемое логическое выражение. Если оно вычисляется со значением .F., то оценивается следующее выражение, если – со значением .T., то функции вернет результат соответствующего выражения eResult.
eOtherwiseResult – результат, возвращаемый, если все выражения lCondition оцениваются со значением .F. Если параметр опущен и все lCondition имеют значение .F., то функция вернет NULL.
Если функция ICASE( ) использована в выражении фильтра, например в опции FOR или WHERE, то необходимо проследить, чтобы функция SYS(3055) задавала необходимый уровень допустимой сложности выражений.
Пример. В выше приведенной функции DoOperation( ) вместо конструкции DO CASE … ENDCASE употребляется функция ICASE( ).
function DoOperation(a, b, op)
return Icase(op == '+', a + b, op == '–', a – b, op == '*', a * b, ;
op == '/' or op == ':', a / b, op == '^', a^b, .F.)
endFunc
Конструкция
DO WHILE lExpression Commands [LOOP] [EXIT] ENDDO
обеспечивает выполнение команд Commands до тех пор, пока истинно логическое выражение lExpression.
Конструкция DO WHILE … ENDDO может включать команды LOOP и EXIT.
LOOP – передает управление на начало конструкции, то есть команде DO WHILE.
EXIT – выполняет выход из конструкции, передавая управление оператору, следующему за командой ENDDO.
Пример (приводится в справке VFP). Вычисляется общая стоимость имеющихся в наличии товаров, цена которых не менее 20 у. е.
close databases
open database (Home(2) + 'Data\TestData')
use Products
set talk off
gnStockTot = 0
&& Просматриваем все записи таблицы Products
do while .T.
if eof( )
exit
endif
if unit_price < 20
skip && Переходим на следующую запись
loop
endif
gnStockTot = gnStockTot + in_stock
skip && Переходим на следующую запись
enddo
clear
? gnStockTot && Выводим результат
Замечание. С позиции структурного программирования приведенный цикл правильнее записать следующим образом:
do while .T. and not eof( )
if unit_price >= 20 then
gnStockTot = gnStockTot + in_stock
endif
skip && Переходим на следующую запись
enddo
С функцией IIF( ) цикл будет еще короче:
do while .T. and not eof( )
gnStockTot = gnStockTot + Iif(unit_price < 20, 0, in_stock)
skip && Переходим на следующую запись
enddo
Конструкция
FOR EACH Var [AS Type [OF Class Library]] IN Group [FOXOBJECT] Commands [EXIT] [LOOP] ENDFOR | NEXT [Var]
обеспечивает выполнение команд Commands для каждого элемента Var массива или коллекции Group.
Опция и параметры:
Type – базовый класс, имя класса или библиотеки типа (только для Intellisense).
Class Library – библиотека классов, содержащая базовый класс, имя класса или библиотеки типа (только для Intellisense).
FOXOBJECT – указывает, что элемент Var будет ссылаться только на VFP-объекты (не COM).
Команды LOOP и EXIT имеют такое же действие, как и в конструкции DO WHILE … ENDDO: LOOP передает управление на начало цикла, EXIT – обеспечивает выход из цикла (прерывание цикла).
Пример 1. См. в описании конструкции IF … ENDIF.
Пример 2 (приводится в справке VFP). Создается экземпляр Microsoft Excel и добавляется новая рабочая книга. Печатаются имена элементов коллекции, которой рабочая книга является.
oExcel = CreateObject("Excel.Application")
oExcel.Workbooks.Add
for each Sheet in oExcel.Sheets
?? Sheet.Name, " " && Напечатает: Лист1 Лист2 Лист3
next Sheet
Пример 3. Выводятся имена файлов всех форм, входящих в активный проект.
&& Проект должен быть открыт
&& Одним из свойств объекта Project является коллекция Files
for each file in _VFP.ActiveProject.Files
&& Проверяем, является ли файл формой
if file.Type = 'K' then
? file.Name && Печатаем имя файла
endif
endfor
Конструкция
FOR Var = nInitialValue TO nFinalValue [STEP nIncrement] Commands [EXIT] [LOOP] ENDFOR | NEXT
обеспечивает выполнение команд Commands заданное число раз.
Если nIncrement > 0, то цикл выполняется до тех пор, пока Var ≤ nFinalValue.
Если nIncrement < 0, то цикл выполняется до тех пор, пока Var ≥ nFinalValue.
Значение 0 для параметра nIncrement недопустимо.
На первой итерации Var = nInitialValue.
Каждое новое значение параметра Var, вычисляемое при передаче управления на начало цикла, равно Var = Var + nIncrement. (Управление на начало цикла передают команды ENDFOR | NEXT и LOOP.)
Если параметр nIncrement опущен, то он принимается равным 1.
Команды LOOP и EXIT имеют такое же действие, как и в конструкции DO WHILE … ENDDO.
Замечание. Параметры nInitialValue, nFinalValue и nIncrement являются числовыми выражениями, вычисляемыми при входе в цикл, поэтому изменение значений nInitialValue, nFinalValue и nIncrement, если они являются переменными, внутри цикла не окажет влияния на число выполняемых итераций. Однако изменение параметра Var внутри цикла влияет на число его выполнений.
Пример 1. См. в описании функции IIF( ).
Пример 2. Выводится номер первой строки двумерного массива, имеющей отрицательный элемент.
declare someArray(4, 5)
someArray = 2
someArray(3, 2) = –1
someArray(4, 3) = –1
&& Массив someArray:
&&
|
2
|
2
|
2
|
2
|
2
|
&&
|
2
|
2
|
2
|
2
|
2
|
&&
|
2
|
–1
|
2
|
2
|
2
|
&&
|
2
|
2
|
–1
|
2
|
2
|
numberOfCols = Alen(someArray, 2) && Число столбцов в массиве
flag = .F.
for iRow = 1 to Alen(someArray, 1)
for iCol = 1 to numberOfCols
if someArray(iRow, iCol) < 0 then
? "Номер первой строки с отрицательным элементом ", iRow
flag = .T.
exit && Выход из внутреннего цикла
endif
endfor
if flag then && Строка найдена
exit && Выход из вешнего цикла
endif
endfor
if not flag
? "В массиве нет отрицательных элементов!"
endif
Замечание. С позиции структурного программирования приведенный цикл лучше переписать следующим образом:
numberOfCols = Alen(someArray, 2) && Число столбцов в массиве
flag = .F.
iRow = 0
do while iRow < Alen(someArray, 1) and not flag
iRow = iRow + 1
iCol = 0
do while iCol < numberOfCols and not flag
iCol = iCol + 1
if someArray(iRow, iCol) < 0 then
? "Номер первой строки с отрицательным элементом ", iRow
flag = .T.
endif
enddo
enddo
|