3. Если первый байт не равен 4, а второй байт равен 4, то первый байт Unicode перекодируется в cp1251.
4. Иначе если первый байт не равен 4 и второй байт не равен 4, то перекодировка не требуется.
5. Добавить полученный символ в новую строку.
Подпрограмма обработки текста кодированного в Unicode для перекодировки в cp1251:
Sub DecUnicodeTo1251(TextUnicode() As String, Text1251() As String)
Dim i As Integer
Dim n As Integer
Dim fstr As String
Dim smb1 As String * 1
Dim smb2 As String * 1
Dim code1 As Byte
Dim code2 As Byte
Dim OutStr As String
'В тексте кодированном в cpUnicode в начале добавляется два символа "ю" и "я"
'Поэтому их надо удалить
fstr = Right(TextUnicode(0), Len(TextUnicode(0)) - 2) 'удаление символов "ю" и "я"
TextUnicode(0) = fstr
For i = 0 To UBound(TextUnicode)
OutStr = ""
For n = 1 To Len(TextUnicode(i))
smb1 = Mid(TextUnicode(i), n, 1)
code1 = Asc(smb1)
smb2 = Mid(TextUnicode(i), n + 1, 1)
code2 = Asc(smb2)
'Проверка по двум байтам:
'Если второй байт равен 4, то первый байт Unicode перекодируется в cp1251
If (code1 <> 4 And code2 = 4) Then OutStr = OutStr & Chr(cpUnicodeTo1251(code1))
'Если первый байт не равен 4, то символ ASCII, и не требует перекодировки
If (code1 <> 4 And code2 <> 4) Then OutStr = OutStr & Chr(code1)
Next n
ReDim Preserve Text1251(i)
Text1251(i) = OutStr
Next i
End Sub
Функции перекодировки кода заданной кодировки в код ср1251:
'перекодирование кода символа из cpКОИ-8R в cp1251
Function cpKoiTo1251(code As Byte) As Byte
Dim c As Byte
c = code
Select Case code
Case 225 To 226c = code - 33Case 228 To 229c = code - 32Case 233 To 240c = code - 33Case 242 To 245c = code - 34Case 193 To 194c = code + 31Case 196 To 197c = code + 32Case 201 To 208c = code + 31Case 210 To 213c = code + 30Case 221c = 249Case 223c = 250Case 217c = 251Case 216c = 252Case 220c = 253Case 192c = 254 | Case 247c = 194Case 231c = 195Case 179c = 168Case 246c = 198Case 250c = 199Case 230c = 212Case 232c = 213Case 227c = 214Case 254c = 215Case 251c = 216 Case 163c = 184Case 214c = 230Case 218c = 231Case 198c = 244 | Case 253c = 217Case 255c = 218Case 249c = 219Case 248c = 220Case 252c = 221Case 224c = 222Case 242c = 223Case 215c = 226Case 199c = 227Case 195c = 246Case 222c = 247Case 219c = 248 Case 200c = 245Case 209c = 255 |
End Select
cpKoiTo1251 = c
End Function
'перекодирование кода символа из cpOEM в cp1251
Function cpOEMTo1251(code As Byte) As Byte
Dim c As Byte
c = code
Select Case code
Case 161c = 192Case 163c = 193Case 236c = 194Case 173c = 195Case 167c = 196Case 169c = 197Case 133c = 168Case 234c = 198Case 244c = 199Case 184c = 200Case 190c = 201Case 199c = 202Case 209c = 203Case 211c = 204Case 213c = 205Case 215c = 206Case 221c = 207Case 226c = 208Case 228c = 209Case 181c = 245Case 164c = 246Case 251c = 247 | Case 230c = 210Case 232c = 211Case 171c = 212Case 182c = 213Case 165c = 214Case 152c = 215Case 246c = 216Case 250c = 217Case 238c = 218Case 242c = 219Case 159c = 220Case 248c = 221Case 170c = 244Case 249c = 249Case 237c = 250Case 241c = 251Case 158c = 252Case 247c = 253Case 150c = 254Case 222c = 255Case 231c = 243Case 245c = 248 | Case 157c = 222Case 224c = 223Case 160c = 224Case 162c = 225Case 235c = 226Case 172c = 227Case 166c = 228Case 168c = 229Case 132c = 184Case 233c = 230Case 243c = 231Case 183c = 232Case 189c = 233Case 198c = 234Case 208c = 235Case 210c = 236Case 212c = 237Case 214c = 238Case 216c = 239Case 225c = 240Case 227c = 241Case 229c = 242 |
End Select
cpOEMTo1251 = c
End Function
'перекодирование кода символа из cp866 в cp1251
Function cp866To1251(code As Byte) As Byte
Dim c As Byte
c = code
Select Case code
Case 128 To 175
c = code + 64
Case 224 To 239
c = code + 16
Case 240
c = 168
Case 241
c = 184
End Select
cp866To1251 = c
End Function
'перекодирование кода символа из Unicode в cp1251
Function cpUnicodeTo1251(code As Byte) As Byte
Dim c As Byte
c = code
Select Case code
Case 16 To 79
c = code + 176
Case 1
c = 168
Case 81
c = 184
End Select
cpUnicodeTo1251 = c
End Function
'перекодирование кода символа из cpMAC в cp1251
Function cpMACTo1251(code As Byte) As Byte
Dim c As Byte
c = code
Select Case code
Case 128 To 159
c = code + 64
Case 224 To 254
c = code
Case 221
c = 168
Case 222
c = 184
Case 223
c = 255
End Select
cpMACTo1251 = c
End Function
'перекодирование кода символа из cpISO в cp1251
Function cpISOTo1251(code As Byte) As Byte
Dim c As Byte
c = code
Select Case code
Case 176 To 239
c = code + 16
Case 160
c = 168
Case 240
c = 184
End Select
cpISOTo1251 = c
End Function
4. Алгоритм сортировки записей исходного файла
Задача сортировки файла формулируется следующим образом. Имеется файл, состоящий из последовательности записей. Одно из полей в составе каждой записи является полем ключа. Файл целиком размещается во внутренней памяти. Требуется вывести файл на внешний носитель так, чтобы записи располагались в заданном порядке следования ключей.
Из возможного множества алгоритмов сортировки файлов более эффективными будут те, которые требуют меньше перестановок записей. В работе рассматривается такой алгоритм, который вообще не требует ни одной перестановки: после подготовительных процедур записи выводятся в файл в заданном порядке следования ключей.
Данное, которое находится в составе записи и значения, которого должны учитываться при сортировке, называется ключом.
Для сортировки записей по заданному ключевому полю удобнее использовать ЗАПИСИ:
1. Первые две строки файла – заголовок и «Шапка» в сортировке не участвуют.
2. Третья и последующие строки преобразуются в ЗАПИСИ типа param:
Type param
prop As String
vol(7) As Single
EndType
Например:
ЗАПИСЬ: | Par.prop | Par.vol(0) | Par.vol(1) | Par.vol(2) | Par.vol(3) |
Строка: | Аммиак NH3 | 15,0 | 28,0 | 15 | 79 |
Разделителем при преобразовании в ЗАПИСЬ является знак горизонтальной табуляции (HT)
Например:
Аммиак NH3HT15,0HT28,0HT15HT79
Подпрограмма разделения строк исходного файла на поля:
Sub seps(str As String, par As param, howpar As Integer)
Dim p As Integer, q As Integer, r As Integer
Dim dlina As Integer
Dim sp As String, smb As String
Dim HT As String * 1
HT = Chr(9)
dlina = Len(str)
If dlina = 0 Then
Exit Sub
End If
r = InStr(str, HT)
par.prop = Left(str, r - 1)
sp = Right(str, dlina - r) & HT
dlina = dlina - r + 1
p = 1: q = 0
Do While p < dlina
r = InStr(p, sp, HT)
smb = Mid(sp, p, r - p)
If smb = "-" Then
par.vol(q) = 0
Else:
par.vol(q) = CSng(smb)
End If
q = q + 1
p = r + 1
Loop
howpar = q
End Sub
Алгоритмсортировки
Решение задачи сортировки файла разбивается на два этапа.
На первом этапе создаётся вспомогательный вектор. На втором этапе формируется выходной файл: первой выводится запись, номер которой 0 затем выводится запись, номер которой 1 и т. д.
Первый этап. Описание алгоритма формирования вспомогательного вектора.
Исходные данные: volVector - массив записей, в составе каждой записи имеется поле ключа Vol(1). В массиве volVector содержится N элементов. доступ к ключу j-ого элемента обозначается так: volVector(j).Vol(1). Тип данного Vol(1) допускает сравнение на равно, больше и меньше. В результате выполнения алгоритма, определяются значения элементов вспомогательного вектора intMesto. В алгоритме используется вспомогательный логический вектор размером N. flag(j)=True обозначает, что элемент volVector(j) доступен для просмотра, но, если flag(j)=False, то элемент volVector(j) исключается из просмотра. В исходном состоянии все элементы вектора flag устанавливаются в значение True. Вспомогательная переменная voltemp хранит текущее минимальное значение Vol(1). Константа voltempимеет тот же тип, что и ключ Vol(1), значение voltemp заведомо больше любого ключа Vol(1).
1. Для каждого iот 0 до N выполнять шаги 1....5. (Индекс i определяет место записи в выходном файле.)
2. Установить voltemp равным 99999 и перейти к шагу 3.
3. Для каждого jот 0 до Nвыполнять шаг 4. (В этом цикле отыскивается претендент на место i.)
4. Если flag(j)=Trueи volVector(j).Vol(1)<=voltemp, выполнить voltemp ← volVector(j).Vol(1); kl←j. (Если элемент volVector(j) доступен и его ключ volVector(j).Vol(1) меньше, чем текущий минимум voltemp, то заменить значение текущего минимума и запомнить его место. Доступность элемента volVector(j) определяется значением True элемента flag(j).
5. ВыполнитьintMesto(i)←kl; flag(kl)←False. (Минимальное значение из множества доступных ключей найдено в записи с индексом kl. Значение kl записывается в intMesto(i), kl-ый элемент вектора volVector помечается как недоступный, исключается из дальнейших действий.)
Второй этап сортировки файла - вывод в рабочий лист Excel и запись в файл на диске.
(mas-массив исходных записей, mm-вспомогательный массив, sk-массив исходных строк)
For q = 0 To h
Cells(q + 3, 1) = mas(mm(q)).prop
For i = 0 To hp - 1
Cells(q + 3, i + 2) = mas(mm(q)).vol(i)
Next i
Print #nf2, sk(mm(q) + 2)
Next q
Подпрограмма первого этапа сортировки (создание вспомогательного массива intMesto):
Sub sort(volVector() As param, intMesto() As Integer, h As Integer)
Dim i As Integer, j As Integer, kl As Integer
Dim highIndex As Integer, lj As Integer
Dim voltemp As Single
Dim flag() As Boolean
h = UBound(volVector)
ReDim intMesto(h)
highIndex = UBound(volVector)
ReDim flag(highIndex)
For i = 0 To highIndex
flag(i) = True
Next i
For i = 0 To highIndex
voltemp = 99999
For j = 0 To highIndex
If flag(j) Then
If volVector(j).vol(1) <= voltemp Then
'если volvector(j) будет меньше или равно voltemp
'то значение текущего минимума voltemp, будет
'заменено на элемент volvector(j)
voltemp = volVector(j).vol(1)
kl = j
End If
End If
Next j
intMesto(i) = kl
flag(kl) = False
Nexti
EndSub
Подпрограмма второго этапа сортировки - вывод результата в рабочий лист Excel и запись в файл на диске:
Sub OutputData(name As String, sk() As String, mm() As Integer, h As Integer, hp As Integer, nf2 As Integer, str As String, mas() As param)
Dim i As Integer, q As Integer
Open name For Output As nf2
Print #nf2, sk(0)
Print #nf2, sk(1)
Cells(1, 1) = sk(0)
For i = 0 To hp
Cells(2, i + 1) = str(i)
Next i
For q = 0 To h
Cells(q + 3, 1) = mas(mm(q)).prop
For i = 0 To hp - 1
Cells(q + 3, i + 2) = mas(mm(q)).vol(i)
Next i
Print #nf2, sk(mm(q) + 2)
Next q
Close #nf2
End Sub
5. Структурная иерархическая схема программы
6. Листинг программы
Модуль 1
Главная программа
'Главная программа
'Чалков С.А. 10.06.2010
SubCore()
Dim st() As String, sk() As String
Dim mm() As Integer, mas() As param
Dim h As Integer, кодировка As String
Dim msg As String
Dim q As Integer, hp As Integer
Dim nf1 As Integer, nf2 As Integer
Dim k As Integer, i As Integer
Dim str As String, indx As Integer
Dim name1 As String, name2 As String
name1 = "d:\ВоспламеняемостьГазов.txt"
name2 = "d:\vba\Save.txt"
nf1 = FreeFile(): nf2 = FreeFile()
Worksheets(1).Select
Call InputData(name1, nf1, st, sk, k)
Call FindCP(st, кодировка, msg, indx): MsgBox кодировка: MsgBox msg
Call Decoder(st, indx, k, sk)
Call ConvertToRecord(sk, k, str, mas, hp)
Call sort(mas, mm, h)
Call OutputData(name2, sk, mm, h, hp, nf2, str, mas)
EndSub
Модуль 2
Ввод данных из файла в память
Sub InputData(name As String, nf1 As Integer, st() As String, sk() As String, k As Integer)
k = 0
Open name For Input As nf1
Do Until EOF(nf1)
ReDim Preserve st(k)
Line Input #nf1, st(k)
ReDim Preserve sk(k)
sk(k) = st(k)
k = k + 1
Loop
Close #nf1
End Sub
Модуль 3
Проверка принадлежности текста к одной из шести кодовых таблиц