Хостинг портала RFpro.ru: Московский хостер Профессиональный ХОСТИНГ на базе Linux x64 и Windows x64 РАССЫЛКИ ПОРТАЛА RFPRO.RU Лучшие эксперты данной рассылки Номер выпуска: | 1408 | Дата выхода: | 27.12.2010, 10:30 | Администратор рассылки: | Лысков Игорь Витальевич (Старший модератор) | Подписчиков / экспертов: | 224 / 68 | Вопросов / ответов: | 1 / 1 | Вопрос № 181458: Здравствуйте, уважаемые эксперты! Прошу Вас ответить на следующий вопрос: "Работа с файлами.Пользователь вводит с клавиатуры имя файла с текстом и имя создаваемого файла, в который будет помещен результат. Слова в строке могут быть разделены ... Вопрос № 181458: Здравствуйте, уважаемые эксперты! Прошу Вас ответить на следующий вопрос: "Работа с файлами.Пользователь вводит с клавиатуры имя файла с текстом и имя создаваемого файла, в который будет помещен результат. Слова в строке могут быть разделены пробелами и знаками препинания. Отсортировать строки файла по длинам" Тип памяти любой. Написание Tasm. (32 бита). (работа внутри тасма. тоесть через ctrl+f8) Отправлен: 19.12.2010, 20:13 Вопрос задал: Ирина (Посетитель) Всего ответов: 1 Страница вопроса » Отвечает Лысков Игорь Витальевич (Старший модератор) : Здравствуйте, Ирина ! Вот Вам программа, которая сортирует указанный файл (< 64к)
Код: ;Пользователь вводит с клавиатуры имя файла с текстом и имя создаваемого файла, ;в который будет помещен результат. Слова в строке могут быть разделены пробелами ;и знаками препинания. Отсортировать строки файла по длинам .model tiny .code .startup ;Определим место для данных за программой ;Для этого сначала ограничим стек 100h и разместим его сразу программой lea ax, last ;последний исползованный адрес and ax, 0fffeh ;сделаем кратным 2 add ax, 100h ;добавим место под стек mov s p, ax ;вершина стека ;Теперь определим сегмент данных add ax, 0fh ;чтобы выровнять с избытком до параграфа (10h) shr ax, 4 ;длина программы+стека в параграфах mov cx, ds ;сегмент программы add ax, cx ;ax - сегмент за стеком - для данных mov segData, ax ;сораним ;и сегмент индексов add ax, 1000h ;размер сегмента данных - 64к mov segIdx, ax ;за ним разместим сегмент индексов
lea dx, sEnterIn ;строка приглашения ввести имя входного файла call GetName ;вводим имя входного файла, результат - в dx jc Finish ;если пустая строка, то выходим
mov ax, 3d00h ;открываем на чтение int 21h jc OpenError ;не найдено - выводим сообщение и выходим mov bx, ax ;handle файла push ds ;сохраним сегмент данных программы mov ax, segData mov ds, ax ;сегмент данных файла xor dx, dx ;начальный адрес mov cx, 0fffdh ;максимальная возможная длина ; (2 байта резерва на возможный до бавочный ; последний eol) mov ah, 3fh ;функция чтения int 21h jc ReadError ;если ошибка, то выводим сообщение и выходим mov si, ax ;длина файла cmp word ptr [si-2], 0a0dh ;проверим, есть ли в конце код конца строки je EolFound ;есть, ну и отлично mov word ptr [si], 0a0dh ;добавим 0d0a add ax, 2 ;и увеличим длину на 2 EolFound: pop ds ;восстановим сегмент данных программы mov FileLen, ax ;сохраним длину файла mov ah, 3eh ;закрываем файл int 21h
call FormIdx ;Сформируем индексы в сегменте индексов
call Sort ;Отсортируем индексы
lea dx, sEnterOut ;строка приглашения ввести имя выходного файла call GetName ;вводим имя выходного файла, результат - в dx jc Finish ;если пустая строка, то выходим
mov ah, 3ch ;создаем выходной файл xor cx, cx ;без атрибутов int 21h jc CreateError ;ошибка - на выход mov bx, ax ;handle
call FormOut ;выводим в отсортированном порядке pushf mov ah, 3eh ;закрываем файл int 21h popf jc WriteError
Finish: ;все сделано... lea dx, sPress ;выведем приглашение нажать на любую клавишу mov ah, 9 int 21h
mov ah, 0 ;ждем клавишу int 16h
mov ax, 4c00h int 21h ;выход в ДОС
;Сообщения об ошибках OpenError: lea dx, sOpenError jmp PrintStr ReadError: pop ds ;т.к. регистр ds был в стеке lea dx, sReadError jmp PrintStr CreateError: lea dx, sCreateError jmp PrintStr WriteError: lea dx, sWriteError PrintStr: ;выводим сообщение mov ah, 9 int 21h jmp Finish
GetName proc ;Вводим строку с именем mov ah, 9 int 21h ;приглашение на ввод имени входного файла
mov bNum, 80 ;максимальный размер буфера для ввода строки lea dx, bNum mov ah, 0ah int 21h ;вводим строку
;отсечем лидирующие пробелы lea si, sName ;введенная строка GNStart: lodsb ;очередной символ cmp al, ' ' je GNStart ;пробелы пропускаем cmp al, 0d h je GNError ;если пустая строка или пробелы, то взведем FC lea dx, [si-1] ;есть начало строки, имени файла GNEnd: ;найдем конец имени - пробел или код 0dh lodsb ;очередной символ cmp al, 0dh je EndFound ;конец строки cmp al, ' ' ;и пробел - нашли конец имени jne GNEnd ;иначе продолжаем искать EndFound: mov byte ptr [si-1], 0 ;вставим 0 в конце имени clc ;есть имя файла ret GNError: stc ;пустая строка ret GetName endp FormIdx proc ;формирование массива индексов push ds es ;будем менять сегментные регистры mov cx, FileLen ;длина данных mov es, segData ;сегмент данных mov ds, segIdx ;сегмент индексов xor di, di ;адрес в сегменте данных xor si, si ;адрес в сегменте индексов mov al, 0dh ;будем искать код 0dh FormIdxLoop: ;цикл по всем символам jcxz FormIdxRet ;cx=0 в конце данных mov bx, di ;запомним начало строки repne s casb ;ищем конец строки, который есть обязательно ; (мы в случае необходимости добавили в конец 0d0a) mov dx, di ;адрес конца строки + 1 sub dx, bx ;длина строки + 1 dec dx ;ровно длина строки mov [si], bx ;сохраняем адрес начала строки mov [si+2], dx ;и длину строки (без 0d0a) add si, 4 ;на следующую запись индекса inc di ;пройдем код 0ah dec cx ;уменьшим для него счетчик символов jmp FormIdxLoop ;пока не пройдем все данные файла FormIdxRet: shr si, 2 ;si - число строк файла! pop es ds mov Rows, si ;запомним число строк файла ret FormIdx endp
Sort proc ;отсортируем индексы методом пузырька push ds mov cx, Rows ;число строк (записей) mov ds, segIdx ;сегмент индексов
cmp cx, 2 ;0 и 1 нет смысла сортировать jb SortRet dec cx ;число сравнений xor si, si ;адрес индекса SortLoop: ;цикл по поиску очередного минимального lea di, [si+4] ;начинаем со следующего push cx ;сохраним счетчик mov ax, [si+2] ;текущий минимальный по адресу [si] SearchMinLoop: ;цикл по всем последующим ;сравниваем текущий со всеми последующими cmp ax, [di+2] ;если текущий минимальный <= последующего, jle SortNext ; то обходим обмен ;меняем местами элементы mov ax, [si] ;меняем местами адреса строк xchg ax, [di] mov [si], ax mov ax, [si+2] ;меняем местами длины строк xchg ax, [di+2] mov [si+2], ax ;по адресу [si+2] и в ax новая минимальная длина SortNext: add di, 4 ;на следующий последующий loop SearchMinLoop add si, 4 ;на следующий текущий pop cx ;восстановим счетчик сравнений loop SortLoop
SortRet: pop ds ret Sort endp
FormOut proc ;выводим в файл все строки в отсорт виде push ds es mov cx, Rows ;число строк mov es, segIdx ;сегмент индексов mov ds, segData ;сегмент данных xor si, si ;адрес индекса WriteLinesLoop: ;по всем строкам push cx ;сохраним счетчик строк mov dx, es:[si] ;адрес строки mov cx, es:[si+2] ;длина строки add cx, 2 ;+ 2 байта 0d0a mov ah, 40h int 21h ;пишем в файл pop cx ;воостановим счетчик строк jc FormOutRet ;ксли ошибка, то FC = 1 add si, 4 ;на след индекс loop WriteLinesLoop clc ;все ок FormOutRet: pop es ds ret FormOut endp
.data sEnterIn db 'Enter input file name: $' sEnterOut db 0ah,'Enter output file name: $' sPress db 0ah,'Press any key$' sOpenError db 0ah,'Open Error',0dh,'$' sReadError db 0ah,'Read Error',0dh,'$' sCreateError db 0ah,'Create Error',0dh,'$' sWriteError db 0ah,'Write Error',0dh,'$'
.data? segData dw ? ;сегмент данных segIdx dw ? ;сегмент индексов FileLen dw ? ;длина файла Rows dw ? ;число строк < br>;буфер для ввода числовой строки (для функции 0ah) bNum db ? ;максимальный размер буфера bCount db ? ;реальный размер строки sName db 80 dup (?) ;сама строка
Last label byte ;последний использованный адрес
end ----- Люби своего ближнего, как самого себя Ответ отправил: Лысков Игорь Витальевич (Старший модератор) Ответ отправлен: 26.12.2010, 00:55 Номер ответа: 265079 Украина, Кировоград Тел.: +380957525051 ICQ # 234137952 Mail.ru-агент: igorlyskov@mail.ru Вам помог ответ? Пожалуйста, поблагодарите эксперта за это! Как сказать этому эксперту "спасибо"? | Отправить SMS #thank 265079 на номер 1151 (Россия) | Еще номера » | Оценить выпуск » Нам очень важно Ваше мнение об этом выпуске рассылки! Скажите "спасибо" эксперту, который помог Вам! Отправьте СМС-сообщение с тестом #thank НОМЕР_ОТВЕТА на короткий номер 1151 (Россия) Номер ответа и конкретный текст СМС указан внизу каждого ответа. Полный список номеров » * Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи. (полный список тарифов) ** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются. *** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании. |
Комментариев нет:
Отправить комментарий