logo search
ИТвМ-12-09-осень2013

Область определения и время жизни переменных

В VISAUL BASIC есть три вида областей определения, характеризующих доступность переменной:

Локальные переменные

Локальными называются переменные, определяемые внутри процедуры или функции. Они доступны только внутри этой процедуры.

Так как локальная переменная A (см. рис. 65) объявляется оператором Dim в соответствующей процедуре, она доступна внутри только этой процедуры. Поэтому не возникает конфликтов при использовании разными процедурами переменных с одним и тем же именем.

При выходе из процедуры все ее локальные переменные сразу же удаляются из памяти, а при новом вызове этой процедуры переменные создаются вновь.

Переменные контейнера

Переменные контейнера определяются в секции (General) (Declarations) с помощью оператора Dim и доступны только внутри соответствующего контейнера, т.е. формы, модуля или класса (см. рис. 66).

FormModule

Рис. 65. Область определения локальных переменных

Form Module

Рис. 66. Область определения переменных контейнера

Глобальные переменные

Глобальные переменные определяются в секции (General) (Declarations) модуля. При этом вместо оператора Dim используется Public. Глобальные переменные доступны во всех модулях и процедурах проекта (см. рис.67).

Локально объявленные переменные при выходе из процедуры удаляются из памяти, а при новом вызове процедуры инициализируются заново. Их содержимое при этом не сохраняется, что не всегда желательно. Этого можно избежать путем расширения области определения, т.е. объявив переменную глобальной или, как минимум переменной контейнера. Но это разрешает доступ к переменной из других процедур.

Form Module

Рис. 67. Область определения глобальных переменных

VISAUL BASIC дает возможность объявлять переменные как статические. При выходе из процедуры содержимое статической переменной сохраняется. При новом вызове этой процедуры переменной присваивается значение, которое она имела при последнем выходе из этой процедуры. Содержимое переменной сохраняется в течение всего времени, пока существует в памяти форма или модуль.

Объявление переменной как статической:

Static Имя_переменной [As Тип_переменной]

Пример:

Private Sub Command1_Click()

Static a As Integer

Dim b As Integer

a=a+1

b=b+1

Print a

Print b

End Sub

Статическая переменная a при каждом щелчке на кнопке Command1 увеличивается на 1. Нестатическая переменная b при каждом щелчке инициализируется заново, поэтому ее значение при выходе всегда равно 1.

Чтобы объявить статическими все локальные переменные процедуры, следует записать ключевое слово Static в заголовке процедуры.

Полное описание общей процедуры:

[ОбластьВидимости] [Static] Sub имяПроцедуры (СписокПараметров)

Операторы

End Sub

Область видимости - это одно из двух ключевых слов Public или Private. Они устанавливают, к какому классу принадлежит процедура: к классу локальных или классу глобальных процедур. Процедура является локальной (Private), если она доступна (видна) только внутри данного модуля и не может быть вызвана из других модулей. Процедура является глобальной (Public), если она доступна (видна) из других модулей.

Наличие или отсутствие ключевого слова Static говорит о статусе локальных переменных, то есть переменных, объявленных внутри этой процедуры. При наличии этого слова локальные переменные будут сохранять свои значения между последовательными вызовами этой процедуры. При отсутствии слова Static -не будут.

Примечание: Чтобы объявить статическими только некоторые переменные, достаточно при описании переменных вместо ключевого слова Dim использовать Static.

Передача параметров в процедуры

В процедурах событий набор параметров зависит от события и не может быть изменен разработчиком.

В общих процедурах количество и порядок используемых параметров определяется разработчиком. В заголовке процедуры можно указывать тип данных для параметров.

В VISAULBASICпараметры могут передаваться двумя способами:

- либо как ссылки (ByRef)

- либо как значение (ByVal)

Если параметр передается как ссылка, то вызванная процедура получает физический адрес памяти переданной переменной. При таком способе передачи можно изменять значение этого параметра. Так как вызываемая и вызывающая процедуры обращаются к одной и той же области памяти, значение переменной для них идентично.

По умолчанию параметры в VISAULBASICпередаются по ссылке, но можно указывать явно ключевое словоByRefперед параметром в заголовке процедуры:

Sub pr1(ByRef n As String)

При передаче параметра по значению VISAULBASICпередает копию содержимого переменной вместо ее адреса в памяти, и функция или процедура не сможет напрямую модифицировать исходное значение. Ключевое словоByValперед параметром должно указываться обязательно:

Functionfkl(ByValkAsString)AsBoolean

VISUAL BASICпозволяет использовать в процедурах именованные параметры и создавать процедуры, в списке которых могут присутствовать необязательные параметры.

Именованные параметры

Использование именованных параметров позволяет передавать часть или все параметры в любом порядке.

При вызове процедуры следует именовать параметры:

имя параметра:=значение

Пример:

PrivateSubSumma(a,b,c)

c=a+b

End Sub

Private Sub Command1_Click()

Summac:=S,b:=val(Text1.Text),a:=val(Text2.Text)

Text3.Text=Str(S)

End Sub

При вызове процедуры можно передавать как неименованные, так и именованные параметры. Однако, при этом как только в списке появился именованный параметр, то все следующие за ним параметры также должны быть именованными.

Необязательные параметры

Необязательным является параметр, значение которого может не задаваться при вызове процедуры. Для того чтобы параметр стал необязательным, перед его именем ставится ключевое слово Optional. Все последующие параметры после первого необязательного параметра также должны быть необязательными.

Пример:

Sub Pr(a, Optional b)

If IsMissing(b) Then

Print a,b

Else

Print a

EndIf

End Sub

Private Sub Command1_Click()

Pr 1

Pr1,2

EndSub

Примечание: В примере показаны два варианта вызова процедуры Pr. В процедуре Pr функцияIsMissingпроверяет передан или нет аргумент типаVariant.

Массивы статические и динамические.

Массив - это набор элементов определенного типа, каждый из которых имеет свой порядковый номер, называемый индексом. Различают массивы статические и динамические.

Границы статического массива устанавливаются на этапе разработки и могут изменяться только в новой версии программы.

Динамические массивы изменяют свои границы в ходе выполнения программы.

Статические массивы нельзя определить локально внутри процедуры, а только глобально или для контейнера.

[Static| Public| Dim] Имя_массива([Нижн_предел To] Верхн_предел) [AsТип_данных]

Динамический массив создается в два этапа. Сначала массив определяют в секции (General) (Declarations) контейнера (Form,Module) без указания размера. Затем с помощью оператораReDimустанавливают фактический размер массива:

Синтаксис оператора ReDim:

ReDim [Preserve] Имя_массива(Границы) [As Тип_данных]

В отличие от DimоператорReDimиспользуется только в процедурах. При этом тип данных указывать не обязательно, особенно если он уже определен оператором Dim. Использование ключевого словаPreserve позволяет сохранить содержимое массива при изменении его размерности (однако, для многомерных массивов можно изменять только последнее измерение).

Пример:

'(General) (Declarations)

Dim a() As Variant

Private Sub Command1_Click()

ReDim Preserve a(5,10)

. . . . . . .

EndSub

Область видимости динамических массивов (контейнерных, глобальных) определяется способом их объявления:

Public– глобальный;

Dim- контейнерный.

При необходимости определения фактического размера массива используются встроенные функции:

Lbound(массив, размерность) - нижняя граница.

Ubound(массив, размерность) - верхняя граница.

Пример ввода данных в динамический массив:

Dim ms() As String

Private Sub Command1_Click()

Cls

ReDimms(0)

s= "Начало работы"

Do Until s = ""

s = InputBox("введите фамилию")

ms(UBound(ms)) = s

ReDim Preserve ms(UBound(ms) + 1)

Loop

ReDim Preserve ms(UBound(ms) - 1)

For i = 0 To UBound(ms)

Print i; " "; ms(i)

Next i

EndSub

VISUAL BASIC позволяет использовать массив в качестве передаваемого в процедуру параметра и в качестве возвращаемого функцией значения.

Пример передачи массива в качестве параметра массива:

Public Sub srt(b() As Integer)

Dim i As Integer, f As Integer, k As Integer

Do

f = 0

For i = LBound(b) To UBound(b) - 1

If b(i) > b(i + 1) Then

k = b(i): b(i) = b(i + 1): b(i + 1) = k: f = 1

End If

Next

Loop While f = 1

End Sub

Private Sub Command1_Click()

Dim a(1 To 5) As Integer

Dim i As Integer

For i = 1 To 5

a(i) = Val(InputBox("Введите число"))

Next

Call srt(a)

Cls

For i = 1 To 5

Print a(i);

Next

End Sub

Пример функции, возвращающей массив:

Public Function VV(ByVal n As Byte) As Byte()

Dim x(1 To n) As Byte, i As Byte

For i = 1 To n

x(i) = Val(InputBox("Введите число"))

Next

VV=x

End Function

Private Sub Commnd1_Click()

Dim b() As Byte, i As Byte

B()=VV(10) ‘вызов функции

For i = 1 To 10

Print b(i)

Next

End Sub

Файлы

Информация хранится на разнообразных носителях в файлах. Процесс работы с файлами состоит из нескольких этапов:

получение дескриптора файла;

открытие файла;

чтение или запись файла;

закрытие файла.

Дескриптор файла

Для связи системы или приложения с файлом имеется канал ввода/вывода. При открытии файлу ставится в соответствие канал с определенным номером. Допустимо использование номеров 1- 511. Каждый открытый файл имеет собственный канал, с помощью которого записываются или считываются данные. Следовательно, для ввода и вывода данных в файл имеет значение не имя файла, а номер канала. Операционная система должна иметь сведения о наличии свободных каналов, которые можно использовать для открытия файлов.

VISAULBASICимеет функциюFreeFile[(дапазонНомеров)], возвращающую номер свободного канала, который можно использовать для работы с файлом. Если свободных каналов нет (открыто максимально допустимое количество каналов), возникает ошибка выполнения. Необязательный параметрдапазонНомеровпозволяет определить диапазон значений, из которых выбирается очередной свободный номер канала:

если 0(по умолчанию) - возвращается номер канала из диапазона 1-255,

если 1 - то из диапазона 256 - 511.

Типы доступа

В VISAUL BASIC реализованы три типа доступа к файлам:

последовательный (для обработки текстовых файлов);

произвольный (для обработки текста или структурированных двоичных файлов с записями фиксированной длины);

двоичный (для обработки произвольно структурированных файлов).

Последовательный файлсостоит из текстовых строкASCII- формата. Любая информация считывается или сохраняется в текстовом виде построчно. Последовательные файлы могут обрабатываться любым текстовым редактором.

Способ открытия файла с последовательным доступом (для чтения, записи или добавления) задается при вызове оператора открытия файла:

Open имяФайла For режим As дескрипторФайла

Где: имяФайла определяет имя открываемого файла; это либo строка символов, заключенная в кавычки, либо выражение, значением которого является строка символов. Она представляет собой путь к открываемому файлу;

режим - это режим доступа, который может иметь значения:

Input(Ввод) - если файл открывается для чтения из него текстовых данных.

Output(Вывод)- если файл открывается для записи в него данных, начиная с первой позиции. Вся имевшаяся в нем старая информация будет стерта.

Append(Дополнение) - если файл открывается для записи в него данных не с первой, а с конечной позиции, так что вся имевшаяся в нем старая информация будет сохранена.

дескрипторФайла- целое число, по которому идентифицируется открываемый файл. Файловые номера используются при выполнении файловых операций в программе.

Все открытые файлы закрываются оператором:

Close[списокДескрипторов]

списокДескрипторов - это записанные через запятую дескрипторы файлов, которые должны быть закрыты. При отсутствии этого параметра будут закрыты все открытые файлы.

Для записив файл используются операторы:

Print #ДескрипторФайла, [СписокЗначений]

Write #ДескрипторФайла, [СписокЗначений]

Где: СписокЗначений - это записанные через разделитель значения (или выражения).

Оба оператора записывают данные в файл текстовыми строками. Текстовая строка - это последовательность символов, которая заканчивается символом перехода на новую текстовую строку или символом возврата каретки (коды 13 и 10). Текстовый файл представляет собой последовательность текстовых строк.

Логика работы операторов WriteиPrintразлична.

Оператор Write

Разделителем в списке значений является запятая. Список значений просматривается последовательно, и элементы этого списка записываются в одну текстовую строку файла через запятую. Элементы типа Stringзаключаются в кавычки. После записи последнего элемента записывается символ перехода на новую строку.

Например, напишем программу записи в текстовый файл следующих строк:

"Иванов", 1982

"Петров", 1984

"Сидорова", 1983

"Крылов", 1980

В каждой строке - фамилия и год рождения.

На рис. 68 в окне редактора кодов приведен текст процедуры создания текстового файла с использованием оператора Write.

Рис. 68.Вариант 1. Использование оператораWrite

Оператор Print

Элементы списка значений в этом операторе должны быть разделены либо точкой с запятой, либо запятой. От этого зависит, как они будут записаны в текстовую строку файла:

если (;) - значения будут записываться подряд, без промежутков между ними;

если (,) - значения будут записываться в 14-символьные зоны вывода.

Кроме того, в списке значений оператора могут присутствовать функции:

Spc(n) - для вставкиnпробелов между значениями в текстовой строке;

Tab(n) - для указания номераnпозиции для записи следующего значения.

На рис. 69 в окне редактора кодов приведен текст процедуры создания текстового файла с использованием оператора Print.

Для чтения из файла используются:

- оператор Input # ДескрипторФайла СписокПеременных

-оператор Line Input#ДескрипторФайлаПеременная

- функция Input (ЧислоСимволов, дескрипторФайла)

Рис. 69.Вариант 2. Использование оператораPrint

Оператор Input

Список переменных- это записанные через запятую переменные любого типа. В каждой текстовой строке файла количество и тип значений должны совпадать с количеством и типом переменных в списке переменных.

Оператор Line Input

Переменная- это переменная типаStringилиVariant. Результатом работы этого оператора является присвоение Переменной значения - всей очередной текстовой строки файла.

Функция Input

ЧислоСимволов - это количество символов, которое надо прочесть из входного файла. Функция возвращает текст в виде символьной строки. Чаще всего эту функцию используют для одновременного чтения всего текстового файла и размещения его в текстовом поле экранной формы.

Рассмотрим примеры чтения созданного в предыдущем примере файла ГодР1.txt:

Аналогичный результат дает работа программы, использующей операторLine Input:

Private Sub Command3_Click()

Dim ts As String

Open "c:\ГодР1.txt" For Input As #1

Do Until EOF(1)

Line Input #1, ts

Print ts

Loop

Close #1

End Sub

Пример использования функции Input:

Private Sub Command3_Click()

Dim ks As Integer

Open "c:\ГодР1.txt" For Input As #1

ks = LOF(1)

Print Input(ks, #1)

Close#1

EndSub

При обработке файлов также используются функции: EOF(дескрипторФайла) - возвращает значениеTrue, если обнаружен конец файла иFalse- в противном случае.

LOF(дескрипторФайла) - возвращает размер текстового файла в символах.

Пользовательский тип данных

Файлы произвольного доступа хранят структурированные данные и состоят из записей.

Запись – это некоторая порция данных, которая имеет строго определенный размер и свой номер в файле.

Доступ к данным произвольного доступа осуществляется по номеру записи. Чтение данных или запись данных в файл произвольного доступа также выполняется записями. Запись файла должна иметь определенную структуру.

Для определения переменных, которые могли бы хранить структуру в VISUALBASIC, нет встроенных типов таких как, например Integer, String и т.д. Однако VISUAL BASIC позволяет создавать на основе встроенных типов так называемые пользовательские типы. К пользовательским типам относиться тип запись. Запись позволяет хранить совокупность данных разного типа и представляет собой структуру, компоненты которой являютсяполями записи.

Все пользовательские типы необходимо объявлять. Это делается следующим образом:

{Private| Public} Type ИмяТипаДанных

Элемент1 As ТипЭлемента1

. . .

ЭлементN As ТипЭлементаN

End Type

Где: ИмяТипаДанных- это имя, которое присваивается определяемому типу данных;

Элемент1- ЭлементN – имена полей записи;

ТипЭлемента– любой встоенный или объявленный ранее пользовательский тип.

Примечание: все данные String должны иметь фиксированную длину.

Пользовательский тип запись следует объявлять как Public в секции General стандартного модуля, если необходимо чтобы он был доступен из всех процедур всех модулей.

Например, определим следующий пользовательский тип данных:

‘(General)(Declarations)

Public Type ДанныеСтудент

Фамилия As String*15

Имя As String*10

Группа As String*4

ОцМатем As Integer

ОцИнфор As Integer

ОцФилос AsInteger

EndType

После определения пользовательского типа данных необходимо объявить переменные, которые будут иметь этот тип.

Объявим переменную Студент, имеющую пользовательский тип ДанныеСтудент и найдем длину записи, которой будет являться любое значение этой переменной:

Dim Студент As ДанныеСтудент, x As Integer

x= Len(Студент)

Переменные пользовательского типа могут быть локальными, глобальными и переменными контейнера

Файлы с произвольным доступом

Открытие файла

Open ИмяФайла For Random [Access доступ] [блокировка] _ As #ДескрипторФайла Len = ДлинаЗаписи

Где: - Random– определяет режим доступа к данным - произвольный;

Access позволяет задать права доступа к открываемому файлу. ПараметрДоступзадается константами: Read – только для чтения, Write – только на запись, Read Write – чтение и запись (действует по умолчанию);

Блокировкапозволяет определить права доступа к данным файла при многопользовательской работе. Параметр может принимать значения:

Shared– файл может использоваться всеми пользователями для чтения и записи;

LockRead– запрещает другим пользователям считывать данные этого файла;

Lock Write – запрещает другим пользователям записывать данные в этом файл;

Lock ReadWrite – запрещает другим пользователям считывать и записывать в файл.

ДлинаЗаписи - целое число. Оно должно быть равно длине переменной пользовательского типа, которая применяется для хранения одной записи файла. Если это значение меньше длины записи, то возникает ошибка, если больше, то будет использоваться больше дискового пространства.

Закрытие файла

См. закрытие текстовых файлов.