Хостинг портала RFpro.ru: Московский хостер Профессиональный ХОСТИНГ на базе Linux x64 и Windows x64 РАССЫЛКИ ПОРТАЛА RFPRO.RU Лучшие эксперты данной рассылки Номер выпуска: | 1450 | Дата выхода: | 24.05.2011, 16:30 | Администратор рассылки: | Лысков Игорь Витальевич (Старший модератор) | Подписчиков / экспертов: | 215 / 64 | Вопросов / ответов: | 1 / 1 | Вопрос № 183242: Здравствуйте, уважаемые эксперты! Прошу помощи в следующем вопросе: Необходимо разработать программу для поиска и удаления файлов по дате в заданном каталоге с подкаталогами. И ещё желательно сделать блок-схему по работе как процедур, так и пр... Вопрос № 183242: Здравствуйте, уважаемые эксперты! Прошу помощи в следующем вопросе:
Необходимо разработать программу для поиска и удаления файлов по дате в заданном каталоге с подкаталогами. И ещё желательно сделать блок-схему по работе как процедур, так и программы в целом.
Платформа: DOS, Тип ассемблера: TASM, Тип процессора: i8086. - вроде бы указал всё нужное.
Заранее спасибо. Отправлен: 19.05.2011, 16:04 Вопрос задал: Денис (Посетитель) Всего ответов: 1 Страница вопроса » Отвечает Лысков Игорь Витальевич (Старший модератор) : Здравствуйте, Денис! Вот и программа. Разберетесь?
Код : .model tiny, pascal ;структура, необходимая для поиска _DTA struc bRes db 21 dup (?) bAttr db ? dwTime dw ? dwDate dw ? ddSize dd ? bName db 13 dup (?) bLast db ? _DTA ends .data NCnt dw 0 ;счетчик найденных файлов NOff dw 0 ;смещение для следующего имени date dw 0 ;дата файла в спец формате mm db '*.*',0 ;маска для поиска sDir db 'Enter directory: $' sDate db 0dh,0ah,'Enter date (dd.mm.yy): $' sFound db 0dh,0ah,'Found $' sFiles db ' files.$' sDel db ' Delete ? (y,n)$' sDel1 db 0dh, 0ah, 'Deleted $' sAny db 0dh,0ah,'Press any key$' ;число дней в месяцах (для контроля правильности даты) ;учитывается високосный февраль nDays db 31,28,31,30,31,30,31,31,30,31,30,31 ;структура для ввода имены каталога _name db 128 cntn db ? dir db 128 dup (?) ;структура для ввода времени _date db 11 cntd db ? dated db 11 dup (?) .code .186 .startup lea dx, sDir ;вводим каталог mov ah, 9 int 21h lea dx, _name mov ah, 0ah int 21h xor bx, bx ;заменим последний код 0dh на 0 mov bl, cntn mov byte ptr dir[bx], 0 repeat: ;цикл ввода правильной даты lea dx, sDate ;вводим дату в виде dd.mm.yy mov ah, 9 ;можно dd.mm и даже dd int 21h lea dx, _date mov ah, 0ah int 21h ;проверяем и конвертируем дату в спец формат call ConvertDate, offset dated jc repeat ;если ошибка, то на повтор mov date, ax ;сохраним дату ;ищем файлы call SearchDir, ax, offset dir ;удаляем call Delete PrintAny: lea dx, sAny mov ah, 9 int 21h xor ax, ax int 16h mov ax, 4c00h int 21h ;вывод на экран ASCII строки PrintStr proc lodsb cmp al, 0 je PrintStrRet int 29h jmp PrintStr PrintStrRet: ret PrintStr endp ;копирование ASCII строки strSrc в strDst CopyStr proc strSrc:word, strDst:word mov si, strSrc mov di, strDst CopyStrLoop: lodsb stosb cmp al, 0 jne CopyStrLoop ret CopyStr endp ;удаление ранее найденных файлов ;с выдачей запроса Delete proc ;выдача сообщения "Found NN files. Delete? (y,n)" lea dx, sFound ;Found mov ah, 9 int 21h mov ax, NCnt ;NN call PrintNum lea dx, sFiles ;files mov ah, 9 int 21h cmp NCnt, 0 ;если ничего не найдего je DelRet ;то нечего и удалять lea dx, sDel ;Delete? (y,n) mov ah, 9 int 21h mov ah, 0 ;Ждем int 16h or al, 20h ;Превратим в маленькую буковку cmp al, 'y' jne DelRet ;не y - ничего не делаем ;удаляем push ds ;перейдем в сегмент с именами mov cx, NCnt ;количество имен mov ax, ds add ax, 1000h ;сегмент с именами mov ds, ax ;ds для адреса имени mov es, ax ;es для поиска следующего xor di, di ;адрес имени xor bx, bx ;счетчик удаленных DeleteLoop: ;по всем именам mov dx, di ;ds:dx адрес имени удаляемого файла mov ah, 41h int 21h ;удаляем! jc DeleteNext inc bx ;считаем реально удаленные DeleteNext: push cx ;найдем путь и имя следующего файла mov al, 0 mov cx, 0ffffh repne scasb ;ищем завершающий 0 pop cx loop DeleteLoop ;по всем pop ds ;востановим сегмент данных программы lea dx, sDel1 ;сообщение Deleted mov ah, 9 int 21h mov ax, bx ;NN call PrintNum lea dx, sFiles ;files mov ah, 9 int 21h DelRet: ret Delete endp ;Рекурсивная процедура поиска файлов ;параметры: дата и путь к каталогу SearchDir proc SDDate:word, SDPath:word local dta:_DTA, olddta:word:2 local NextPath:byte:128 local PathPos:word ;скопируем путь в локальный буфер lea ax, NextPath call CopyStr, SDPath, ax ;добавим в конце слеш, если его нет dec di cmp byte ptr [di-1],':' ;после диска слеш не добавляем! je SetLen cmp byte ptr [di-1],'\' je SetLen mov word ptr [di], '\' inc di SetLen: mov PathPos, di ;сохраним позицию, куда будем писать call CopyStr, offset mm, di ;добавим маску *.* push es ;сохраним адрес старой DTA mov ah, 2fh int 21h mov olddta, bx mov olddta+2, es pop es mov ah, 1ah ;установим новую DTA lea dx, dta int 21h mov ah, 4Eh ;Ищем первый файл по маске lea dx, NextPath ;путь с маской для поиска mov cx, 10h ;ищем файлы с поддерикториями mov di, SDDate ;дата, которую будем искать DirLoop: int 21h ;ищем первого/следующего jc found_error ;ошибка? push di ;сохраним дату lea ax, dta.bName ;скопируем имя найденного файла/каталога call CopyStr, ax, PathPos ;с позиции PathPos (за слешем) pop di test byte ptr dta.bAttr, 10h ;проверим атрибут - подкаталог? jz FileFound ;нашли файл ;подкаталог cmp word ptr dta.bName, '.' ;. и .. пропустим je next cmp word ptr dta.bName, '..' je next lea ax, NextPath call SearchDir, di, ax ;ищем в поддиректории jmp next FileFound: cmp dta.dwDate, di ;для файла сравниваем даты jne next push di es ;дата равна требуемой! mov ax, ds ;сохраним путь с именем add ax, 1000h ;в сегменте за программой mov es, ax lea ax, NextPath call CopyStr, ax, NOff mov NOff, di ;сохраним адрес для следующего имени pop es di inc NCnt ;считаем mov al, 0dh ;выведем на экран int 29h mov al, 0ah int 29h lea si, NextPath call PrintStr next: mov ah, 4Fh ; Ищем следующий jmp DirLoop ; Продолжаем found_error: cmp ax, 12h ; ошибка 12h - завершение поиска je finish ;здесь анализ всех остальных ошибок ;надо бы, для полноты картины, проанализироать, ;но можно убрать вообще все от found_error до finish (последнюю оставить) finish: push ds ;восстановим DTA mov ah, 1ah lds dx, dword ptr olddta int 21h pop ds ret SearchDir endp ;определение, является ли год nYear високосным ;параметры: ah - число дней в месяце, ;bh - месяц (1-12), в случае високосного ;года увеличиваем для февраля ah на 1 ;алгоритм: ; 1. Год делится на 400 -> високосный -> конец ; 2. Год делится на 100 -> не високосный -> конец ; 3. Год делится на 4 -> високосный -> конец ; 4. Год не високосный -> конец IsVisokosny proc nYear:word cmp bh, 2 jne IVRet ;рассматриваем только 2 месяц xor cx, cx ;добавка = 0 push ax push dx mov si, 400 mov ax, nYear xor dx, dx div si ;делим на 400 test dx, dx jz VisokosnyYes ;нацело - високосный mov si, 100 mov ax, nYear xor dx, dx div si ;делим на 100 test dx, dx jz VisokosnyNo ;нацело - невисокосный mov ax, nYear test al, 3 jnz VisokosnyNo ;на 4 не делится - невисокосный VisokosnyYes: ;високосный inc cx ;добавка = 1 VisokosnyNo: pop dx pop ax add ah, cl ;добавляем поправку IVRet: ret IsVisokosny endp ;ввод числа (части даты) GetNum proc lodsb ;первый символ sub al, '0' jc GNErr ;< 0 - ошибка cmp al, 9 ja GNErr ;> 9 - ошибка mov dl, al ;сохраним lodsb ;следующий символ cmp al, 0dh je GNRet ;конец строки - на выход cmp al, '.' je GNRet ;точка - на выход sub al, '0' jc GNErr ;< 0 - ошибка cmp al, 9 ja GNErr ;> 9 - ошибка xchg al, dl mov ah, 10 mul ah add dx, ax ;в dx день lodsb ;следующий символ cmp al, 0dh je GNRet ;конец строки - на выход cmp al, '.' jne GNErr ;точка - на выход GNRet: clc ;все ок ret GNErr: stc ;ошибка ret GetNum endp ;проверка даты на корректность ;bl - день, bh - месяц, dx - год CmpDate proc xor ax, ax mov al, bh ;месяц cmp al, 1 jl CmpDateErr cmp al, 12 jg CmpDateErr ;должен быть [1,12] cmp bl, 1 jl CmpDateErr ;день от 1 до максимального для месяца mov si, ax ;месяц mov ah, nDays[si-1] ;число дней в месяце call IsVisokosny,dx ;поправка на високосный год cmp bl, ah ;проверка на макс число jg CmpDateErr clc ;дата корректна ret CmpDateErr: stc ;ошибка ret CmpDate endp ;конвертация даты в спец формат ;параметр - адрес строки с датой dd.mm.yy ConvertDate proc pDate:word mov si, pDate ;адрес строки xor dx, dx ;обнулим на всякий случай call GetNum ;день jc CDErr ;ошибка? mov bl, dl ;сохраним в bl cmp al, 0dh ;конец строки? je CDDay ;доформируем текущей датой call GetNum ;месяц jc CDErr ;ошибка? mov bh, dl ;сохраним в bh cmp al, 0dh ;конец строки? je CDMonth ;доформируем текущей датой call GetNum ;год jc CDErr ;ошибка? cmp al, 0dh ;если не конец строки jne CDErr ;то ошибка! add dx, 2000 ;добавим до года старшие разряды CDCmpDate: call CmpDate ;проверим на корректность jc CDErr ;ошибка? ;сконвертируем в спец формат sub dx, 1980 ;yyyyyyym mmmddddd - побитное содержимое полей shl dx, 9 xor ax, ax mov al, bh shl ax, 5 or al, bl or ax, dx clc ret CDErr: stc ;ошибка ret CDMonth: mov ah, 2ah ;добавим текущий год int 21h mov dx, cx jmp CDCmpDate ;на проверку CDDay: mov ah, 2ah ;добавим текущие месяц и год int 21h mov bh, dh mov dx, cx jmp CDCmpDate ;на проверку ConvertDate endp PrintNum proc ;вывод беззнакового числа из ax push cx ;сохраним счетчик колонок mov bx, 10 ;будем делить на 10 xor cx, cx ;счетчик цифр DivLoop: xor dx, dx ;готовимся к делению dx:ax / bx div bx ;ax - частное, dx - остаток=очередной младшей цифре push dx ;сохраним цифру в стеке inc cx ;посчитаем test ax, ax ;продолжим, пока не 0 jnz DivLoop mov ah, 2 ;функция вывода PrintLoop: ;будем выводить в обратном порядке, начиная со старшей шифры pop ax ;восстановим очередной разряд or al, '0' ;превратим в символ int 29h ;выведем loop PrintLoop pop cx ;восстановим счетчик колонок матрицы ret PrintNum endp end ----- Люби своего ближнего, как самого себя Ответ отправил: Лысков Игорь Витальевич (Старший модератор) Ответ отправлен: 22.05.2011, 23:09 Номер ответа: 267299 Украина, Кировоград Тел.: +380957525051 ICQ # 234137952 Mail.ru-агент: igorlyskov@mail.ru Вам помог ответ? Пожалуйста, поблагодарите эксперта за это! Как сказать этому эксперту "спасибо"? | Отправить SMS #thank 267299 на номер 1151 (Россия) | Еще номера » | Оценить выпуск » Нам очень важно Ваше мнение об этом выпуске рассылки! Скажите "спасибо" эксперту, который помог Вам! Отправьте СМС-сообщение с тестом #thank НОМЕР_ОТВЕТА на короткий номер 1151 (Россия) Номер ответа и конкретный текст СМС указан внизу каждого ответа. Полный список номеров » * Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи. (полный список тарифов) ** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются. *** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании. |
Комментариев нет:
Отправить комментарий