Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Redim Preserve Mass (5) as String






Идем дальше. Поместим на форму объекты Dir1 и Text1. Начнем писать код. Обратите внимание, что процедуры Form_Load у нас не будет, так как под это событие обрабатывать нам нечего. Ну-с, фигачим

Option Explicit
'Установим начальную нумерацию массива с единицы, сейчас так удобнее
Option Base 1
'объявим переменные
Dim OurDir As String 'для директории, где будем искать файлы
Dim FileName As String 'для имен находимых файлов
Dim X As Long 'просто для цикла
'и, наконец, наш динамический массив, как строковый
Dim Files() As String

Кроме того, поскольку одни имена - это уж совсем скучно, то мы еще во вторую размерность массива выведем атрибуты файла. Атрибуты, это когда по файлу шлепаешь правой кнопкой мыши и в выпавшем меню выбираешь " Свойства ". Тогда снизу окна этих свойств можно увидеть галочки рядом с загадочными словами " Только чтение", " Скрытый" и " Архивный". Именно эти свойства можно устанавливать или получать с помощью оператора SetAttr и функции GetAttr. Весь геморрой в том, что этот атрибут представляет из себя число, получаемое из суммы значений атрибутов, приведенных в таблице ниже, и чтобы понять, какой атрибут все-таки у файла, нужно " с помощью оператора And выполнить поразрядное сравнение значения". Друзья мои. Это цитату из Help5 я привел для того, чтобы можно было почувствовать разницу между " академическим" и " вольным" изложением проблемы. Короче, привожу таблицу этих атрибутов:

Константа Значение Описание
vbNormal   Обычный.
vbReadOnly   Только для чтения.
vbHidden   Скрытый.
vbSystem   Системный.
vbDirectory   Каталог или папка.
vbArchive   Архивный.

Из всей этой дребедни нам нужны три константы: vbArchive, vbReadOnly и vbHidden для этого самого " поразрядного сравнения". Делается это так:
Чтобы узнать, только для чтения ли этот файл:
Переменная = GetAttr(" полный путь к файлу") And vbReadOnly
Если в Переменной не ноль, то файл - только для чтения. Аналогично для других констант.
Чтобы установить аттрибут, например " Архивный" для файла:
SetAttr " C: \Andrey\index.htm", vbReadOnly
при этом уже установленные атрибуты файла сбрасываются. Если надо установить атрибуты " только для чтения" и " архивный":
SetAttr " C: \Andrey\index.htm", vbReadOnly +vbArchive
Все просто, а по сути - издевательство. Про атрибуты - все. Более интересные данные о файлах мы получим, когда начнем использовать FSO. Но об этом не сегодня.
Итак, для хранения атрибута (на основании " поразрядного сравнения") продолжаем объявлять переменные (еще две)

Dim Attr As Long 'числовая, для атрибута файла
Dim AttributFile As String 'строковая, для записи атрибута в виде слов

Напишем маленькую процедурку для Dir1 на событие Change. Дело в том, что событие Change наступает при двойном клике, а я и хочу, чтобы директория для поиска файлов устанавливалась по двойному клику. В этой процедурке мы очистим Text1 и обнулим переменные, ну и главное, запишем в переменную OurDir полный путь к директории, после чего перейдем к другой поцедуре - ScanDir, где собственно и будем искать файлы и записывать их имена и атрибуты в наш массив Files.

Private Sub Dir1_Change()
Text1.Text = " "
FileName = " "
X = 0
OurDir = Dir1.Path
ScanDir 'переходим к процедуре сканирования файлов

End Sub

Далее в процедуре ScanDir все, с учетом комментариев, понятно:

Private Sub ScanDir()
FileName = Dir(OurDir & " \*.*", 0) 'присваиваем переменной значение функции Dir для всех файлов

ReDim Files(2, 1) 'переобъявляем массив с минимальной размерностью, иначе может возникать ошибка
Do While FileName < > " " 'запускаем цикл, до тех пор, пока Dir не вернет пустую строку
X = X + 1 'счетчик элементов массива

ReDim Preserve Files(2, X) 'переобъявляем массив по счетчику, сохраняя уже имеющиеся в нем данные
AttributFile = " " 'обнуляем переменные
Attr = 0
'проверяем файл на атрибут архивный
Attr = GetAttr(OurDir & " \" & FileName) And vbArchive

If Attr > 0 Then AttributFile = AttributFile & " Архивный"
'проверяем файл на атрибут только для чтения
Attr = GetAttr(OurDir & " \" & FileName) And vbReadOnly

If Attr > 0 Then AttributFile = AttributFile & " Только чтение"
'проверяем файл на атрибут скрытый для порядка, Бейсик все равно не видит такие файлы
Attr = GetAttr(OurDir & " \" & FileName) And vbHidden

If Attr > 0 Then AttributFile = AttributFile & " Скрытый"

Files(1, X) = FileName 'пишем в массив имя файла
Files(2, X) = AttributFile 'пишем в массив атрибут файла
FileName = Dir() 'запускаем функцию Dir без атрибутов

Loop 'и так в цикле, пока файлы в директории не закончатся

If X > 0 Then
Sort ' если хоть один файл найден,
'отправляемся к процедуре сортировки

Else
Text1.Text = " Файлов не найдено" 'в противном случае выводим сообщение.

End If
End Sub

Основная прелесть массивов в том, что с данными, записанными в них, можно что угодно делать: сортировать, разбивать на группы, осуществлять поиск, делать выборки и т.п. Сейчас мы наш массив отсортирум по возрастанию имен файлов. Скажу сразу, что алгоритмы сортировки разработаны и существуют давно. Приводимый в примере был разработан лично мною, а возможное совпадение его с другими алгоритмами совершенно случайно. Но прежде, чем перейти к сортировке, я хочу рассказать вот о чем.
Поскольку количество элементов нашего массива меняется, а для сортировки его с помощью циклов For...Next нам надо точно знать минимальный (нижняя граница) и максимальный (верхняя граница) доступные значения индекса массива, то я использую функции LBound для определения минимального индекса и UBound для определения максимального индекса указанной размерности. Синтаксис их такой

Переменная=LBound(Massive, 1) 'возвращает в Переменную минимальный индекс массива Massive по размерности 1.
Переменная=UBound(Massive, 1) 'возвращает в Переменную максимальный индекс массива Massive по размерности 1.

Надо сказать, что размерность - не обязательный параметр и по-умолчанию принимается за единицу.
Теперь перейдем к сортировке массива:

Private Sub Sort() 'процедура сортировки
Dim K As Long
Dim N As Long
Dim y As Long 'просто для цикла For...Next
Dim Peremen As String 'для временного храненения из массива имени файла
Dim Peremen2 As String 'и атрибута файла
Dim NomerPerem As String
Dim NomerPerem2 As String
'сортировка массива
K = LBound(Files, 2) 'присваиваем переменной К начальное значение массива - 1 (нижняя граница)

For y = LBound(Files, 2) To UBound(Files, 2) 'просматриваем все строки массива с нижней до верхней границы
Peremen = Files(1, y) 'присваиваем каждую строку в переменные
Peremen2 = Files(2, y)
'вложенный цикл

For N = y To UBound(Files, 2) 'просматриваем строки массива, начиная с той,
'значения которой храняться в переменных Peremen и Peremen2

If Files(1, N) < Peremen Then 'если значение в массиве меньше, чем в переменной
Peremen = Files(1, N) 'то присваиваем переменным Peremen и Peremen2 новые, меньшие значения
Peremen2 = Files(2, N)
K = N 'присваиваем номер найденного элемента массива переменной K

End If
Next N
'конец вложенного цикла
NomerPerem = Files(1, y) 'сохраняем в переменных старые значения строки массива
NomerPerem2 = Files(2, y)
Files(1, y) = Peremen ' и присваиваем этой строке массива новые
Files(2, y) = Peremen2
If K > 0 Then 'если K не ноль,
Files(1, K) = NomerPerem 'то строке К присваиваем старые значения из строки y
Files(2, K) = NomerPerem2
End If
Peremen = " " 'обнуляем переменные
Peremen2 = " "
K = 0
Next y

'конец сортировки
'просто выводим в Text1 отсортированные значения массива
For X = 1 To UBound(Files, 2)
Text1.Text = Text1.Text & Files(1, X) & Files(2, X) & vbCrLf
Next X

End Sub

Исходник программы можно, как всегда, скачать вверху страницы.

Присвоение содержимого одного массива другому.

Можно ли присвоить один массив другому не по отдельному элементу (в цикле), а сразу?
Visual Basic 6.0 и версии выше дают возможность проводить операции присваивания с массивами точно также, как с переменными. Теперь нет необходимости создавать цикл For...Next для присваивания одного массива другому по каждому элементу. Достаточно написать такой оператор
NewMassive=OldMassive
и содержимое массива OldMassive присвоится массиву NewMassive.
Однако при этом следут учитывать, что для исключинения ошибок при таком присвоении, желательно соблюдать одинаковую размерность и тип массивов. Хотя при присвоении динамического массива динамическому массиву, массив в левой части оператора изменяется, как бы подстраивается под оператор в правой части. Однако при работе со статическими массивами возможна ошибка компиляции. Кроме того при присвоении, например массива типа Long типу Integer может возникнуть ошибка переполнения (Owerflow). В программе операция присвоения может выглядеть приблизиельно так (на форме должны быть кнопка Command1 и текстбокс Text1):

Option Explicit
Dim OldMassive() As Long

Dim NewMassive() As Long

Private Sub Command1_Click()
Dim x As Long

For x = 0 To 999 'просто заполнение массива цифрами
ReDim Preserve OldMassive(x)
OldMassive(x) = x
Next x

NewMassive = OldMassive 'присоение массивов

For x = 0 To UBound(NewMassive) ' считывание нового массива в Text1
Text1.Text = Text1.Text & NewMassive(x) & vbCrLf
Next x

End Sub

Я думаю, особых комментариев здесь не требуется.

 

Как бы правильно не был бы написан код программы и как бы безошибочно, казалось, программа бы не работала, всегда есть возможность для возникновения непредвиденных ситуаций, когда VB не может выполнить корректно какой-нибудь оператор, что приводит к аварийному завершению программы (фатальный крах). При этом возможна еще и потеря данных, если в это время происходило, например, копирование файла или передача информации. В большинстве своем это ошибки вызваны внешними событиями, например пустой дисковод, когда твоя программа обращается к дискете, отсутствие того файла, который ты пытаешься открыть для, например, чтения, а также ошибки переполнения (когда не хватает памяти для рисунков и ли печати), сетевые сбои, проблемы с буфером обмена и много чего еще. Скажу сразу, что предусмотреть все возможные ситуации практически невозможно, особенно если твоим продуктом будет пользоваться сторонний юзер. Юзера крайне изобретательны. Я не раз сталкивался с возниковением таких ситуаций, спровоцированных юзером, которые у меня, например, в голове не укладываются, и которые потом смоделировать практически невозможно. Видимо по какому-то озарению свыше, юзер может добиться, таких катастрофических результатов, которых я достигнуть при всей внутренней мобилизации сил своего хилого организма не в состоянии. Если поставить перед собой цель создать программу, всегда работающую корректно, можно раздуть код этой программы до безумных размеров и все равно полного успеха не добиться. Microsoft, например, не добился.

Хотя и не все ошибки VB может перехватывать (их полный список можно найти здесь), однако избегать стандартных ошибок, обрабатывать явно возможные ошибки мы просто обязаны. Мне представляется, что для исключения фатальных сбоев надо придерживаться следующей стратегии.

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

Во-вторых, надо стараться избегать возникновения ошибки программно, тогда ее не придется отслеживать и обрабатывать. Ярким примером такой ситуации может служить программа Scandisk, которую мы рассматривали в прошлой, 10-ой главе. Когда мы тыкали мышью в Dir1 по директориям, все было нормально, при этом выполнялся следующий оператор:
FileName = Dir(OurDir & " \*.*", 0) 'присваиваем переменной значение функции Dir для всех файлов
Если же мы кликали по верхней строке с именем не директории, а диска, возникала ошибка 52 " Неправильное имя файла, или номер". А дело то всего лишь в слеже, который мы поставили в операторе. Дело в том, что функция Dir возвращает имя диска со слежом в конце строки, а имя директории - нет. Если мы его уберем и оператор будет выглядеть так
FileName = Dir(OurDir & " *.*", 0) 'присваиваем переменной значение функции Dir для всех файлов
вот тогда на диске оператор сработает правильно, зато перестанет читать директории. Можно конечно обработать эту ошибку, о чем мы будем говорить ниже, по ее номеру, но тогда в трех нижних операторах
Attr = GetAttr(OurDir & " /" & FileName)...
той же причиной будет также вызвана ошибка, но с другим номером - 75 " Ошибка доступа пути или файла". Тогда придется обрабатывать и ее. Это тоже вариант. Но по-моему логичнее сразу записать в переменную Ourdir правильный путь при любом раскладе. И надо-то для этого всего лишь убрать слеж из четырех операторов, где возникает ошибка, а в процедуру Dir1_Change добавить проверку, которая добавляет слеж при его отсутствии:
If Right(OurDir, 1) < > " \" Then OurDir = OurDir & " \" 'добавленный оператор для устранения ошибки
вот и все дела. Полный исправленный код, если что не понятно, можно скачать здесь.

В-третьих, при обращении к внешним источникам, в том числе к файлам, для получения или вывода информации надо предполагать, что возможно они будут недоступны. Кроме того, надо подумать, какие еще фатальные ситуации могут возникнуть. Вот тут уже надо обрабатывать ошибки конкретно.
Давайте создадим новый exe-проект. По мере необходимости на форму будем класть командные кнопки и в их процедуре отлавливать ошибки. Возьмем пример самой распространенной ошибки - нет того файла, который нам как раз крайне необходим. Положим на форму кнопку Command1 (она будет называться Resume Next) и в ее процедуре напишем операторы открытия файла " aaa.txt" для последовательного чтения.






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.