Среда, 16.07.2025, 05:33 Приветствую Вас Гость

On-line: Книги, учебники, статьи

Главная | Регистрация | Вход | RSS

Глава 5. Управление файлами(5)

Рис. 2.5.3(2). Вывод на консоль содержимого текстового фаша. Второй способ.

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

Основным признаком текстового файла является то, что он состоит из строк разной длины. Строки отделены друг от друга разделителями. Чаще всего это последовательность двух кодов - 13 и 10. Возможны и другие варианты, например, некоторые DOS-редакторы отделяли строки только одним кодом 13.

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

  1. Побайтное чтение из файла. Как только достигаем символа-разделителя, производим действие над считанной строкой и переходим к чтению следующей строки. При этом, разумеется, следует учесть, что на конце файла может не быть символа-разделителя. Если кто-то решит, что это слишком медленный способ, то замечу, что Windows неплохо кэширует диск, так что все выглядит не так уж плохо.
  2. Чтение в небольшой буфер, но так чтобы туда входила, по крайней мере, одна строка. Прочитав, находим в буфере конец строки и производим над ней какое-либо действие. Далее следует обратиться к файлу и передвинуть указатель так, чтобы он был в файле на начале следующей строки и, разумеется, повторить действие.
  3. Чтение в произвольный буфер. После чтения производится поиск всех строк, попавших в буфер, и совершение над ними действий. При этом с большой вероятностью должна возникнуть ситуация, когда одна строка неполностью умещается в буфере. Мы обязаны учесть такую возможность.
  4. Чтение в буфер, в который помещается весь файл. Это частный случай третьего подхода, и наиболее простой с точки зрения программирования.

В программе на Рис. 2.5.4 реализуется третий подход.

; файл FILES2.ASM
.386P
; плоская модель
.MODEL FLAT, stdcall
; константы
STD_OUTPUT_HANDLE equ -11
GENERIC_READ equ 80000000h
GENERIC_WRITE equ 40000000h
GEN = GENERIC_READ or GENERIC_WRITE
SHARE = 0
OPEN_EXISTING equ 3
; прототипы внешних процедур
EXTERN ExitProcess@4:NEAR
EXTERN GetCommandLineA@0:NEAR
EXTERN CreateFileA@28:NEAR
EXTERN CloseHandle@4:NEAR
EXTERN ReadFile@20:NEAR
EXTERN WriteFile@20:NEAR
EXTERN CharToOemA@8:NEAR
;-------------------------------------------------
; директивы компоновщику для подключения библиотек
includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\kernel32.lib
;-------------------------------------------------

; сегмент данных
_DATA SEGMENT DWORD PUBLIC USE32 'DATA'
 HANDL DWORD ? ; дескриптор консоли
 HFILE DWORD ? ; дескриптор файла
 BUF DB 100 DUP (0) ; буфер для параметров
 BUFER DB 1000 DUP (0) ; буфер для файла
 NAMEOUT DB "CONOUT$"
 INDS DD 0 ; номер символа в строке
 INDB DD 0 ; номер символа в буфере
 NUMB DD ?
 NUMC DD ?
 PRIZN DD 0
 STROKA DB 300 DUP (0)
_DATA ENDS

; сегмент кода
_TEXT SEGMENT DWORD PUBLIC USE32 'CODE'
START:
; получить HANDLE вывода (консоли) как файла
 PUSH 0
 PUSH 0
 PUSH OPEN_EXISTING
 PUSH 0
 PUSH 0
 PUSH GEN
 PUSH OFFSET NAMEOUT
 CALL CreateFileA@28
 MOV HANDL,EAX
; получить количество параметров
 CALL NUMPAR
 CMP EAX, 1
 JE NO_PAR
;---------------------------------------------------
; получить параметр номером EDI
 MOV EDI,2
 LEA EBX,BUF
 CALL GET PAR
; открыть файл
 PUSH 0
 PUSH 0
 PUSH OPEN_EXISTING
 PUSH 0
 PUSH 0
 PUSH GEN
 PUSH OFFSET BUF
 CALL CreateFileA@28
 CMP EAX,-1
 JE NO_PAR
 MOV HFILE, EAX
;++++++++++++++++++++++++++++
L00:
; читать 1000 байт
 PUSH 0
 PUSH OFFSET NUMB
 PUSH 1000
 PUSH OFFSET BUFER
 PUSH HFILE
 CALL ReadFile@20
 MOV INDB, 0
; проверим, есть ли в буфере байты
 CMP NUMB, 0
 JZ _CLOSE
; заполняем строку
L001:
 MOV EDI,INDS
 MOV ESI,INDB
 MOV AL,BYTE PTR BUFER[ESI]
 CMP AL,13 ; проверка на конец строки
 JE _ENDSTR
 MOV BYTE PTR STROKA[EDI],AL
 INC ESI
 INC EDI
 MOV INDS,EDI
 MOV INDB,ESI
 CMP NUMB, ESI ; проверка на конец буфера
 JNBE L001
; закончился буфер
 MOV INDS,EDI
 MOV INDB,ESI
 JMP L00
_ENDSTR:
; делаем что-то со строкой
 CALL OUTST
; обнулить строку
 MOV INDS,0
; перейти к следующей строке в буфере
 ADD INDB,2
; не закончился ли буфер?
 MOV ESI,INDB
 CMP NUMB, ESI
 JAE L001
 JMP L00
;++++++++++++++++++++++++++++++
_CLOSE:
; проверим, не пустая ли строка
 CMP INDS,0
 JZ CONT
; делаем что-то со строкой
 CALL OUTST
CONT:
; закрыть файлы
 PUSH HFILE
 CALL CloseHandle@4
; конец работы программы
NO_PAR:
 PUSH 0
 CALL ExitProcess@4

; область процедур
; процедура определения количества параметров в строке
; определить количество параметров (->EAX)
NUMPAR PROC
 CALL GetCommandLineA@0
 MOV ESI,EAX ; указатель на строку
 XOR ECX,ECX ; счетчик
 MOV EDX,1 ; признак
L1:
 CMP BYTE PTR [ESI],0
 JE L4
 CMP BYTE PTR [ESI],32
 JE L3
 ADD ECX,EDX ; номер параметра
 MOV EDX,0
 JMP L2
L3:
 OR EDX,1
L2:
 INC ESI
 JMP L1
L4:
 MOV EAX,ECX
 RET
NUMPAR ENDP

; получить параметр из командной строки
; EBX - указывает на буфер, куда будет помещен параметр
; в буфер помещается строка с нулем на конце
; EDI - номер параметра
GETPAR PROC
 CALL GetCommandLineA@0
 MOV ESI,EAX ; указатель на строку
 XOR ECX,ECX ; счетчик
 MOV EDX,1 ; признак
L1:
 CMP BYTE PTR [ESI],0
 JE L4
 CMP BYTE PTR [ESI],32
 JE L3
 ADD ECX,EDX ; номер параметра
 MOV EDX,0
 JMP L2
L3:
 OR EDX,1
L2:
 CMP ECX,EDI
 JNE L5
 MOV AL,BYTE PTR [ESI]
 MOV BYTE PTR [EBX],AL
 INC EBX
L5:
 INC ESI
 JMP L1
L4:
 MOV BYTE PTR [EBX],0
 RET
GETPAR ENDP

; вывести строку в консоль с разделителем
OUTST PROC
 MOV EBX,INDS
 MOV BYTE PTR STROKA[EBX],0
 PUSH OFFSET STROKA
 PUSH OFFSET STROKA
 CALL CharToOemA@8
; в конце строки - разделитель
 MOV BYTE PTR STROKA[EBX],6
 INC INDS
; вывести строку
 PUSH 0
 PUSH OFFSET NUMC
 PUSH INDS
 PUSH OFFSET STROKA
 PUSH HANDL
 CALL WriteFile@20
 RET
OUTST ENDP
_TEXT ENDS
END START

Рис. 2.5.4. Пример обработки текстового файла.

Программа на Рис. 2.5.4 демонстрирует один из возможных алгоритмов обработки текстового файла - построчное чтение текстового файла. Часть программы, занимающаяся чтением и анализом текстового файла, сосредоточена между метками L00 и CONT. Детально разберитесь в алгоритме и проникнитесь тем, что язык высокого уровня никогда не будет стимулировать написание таких алгоритмов, а значит, язык ассемблера делает нас интеллектуально богаче.


Вход на сайт
Поиск
Календарь
«  Июль 2025  »
ПнВтСрЧтПтСбВс
 123456
78910111213
14151617181920
21222324252627
28293031
Архив записей
Наш опрос
Как Вам удобнее??
Всего ответов: 341
Мини-чат
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Статистика

    Онлайн всего: 1
    Гостей: 1
    Пользователей: 0