Здравствуйте, Ivan Afonin!
Вот и программа.
Единственный момент, на который хочу обратить внимание:
Подпрограмма analize, которая считает вхождения символа в строке,
портит строку - прописывает на всех последующих местах, где находит данный
символ, ноль. Это сделано с целью избежать повторного анализа данного символа.
181127-block-sch.doc (41.0 кб)[code h=200];Разработать подпрограмму, которая подсчитывает, сколько раз за-
;данный символ встречается в строке. Разработать программу, которая
;вводит с клавиатуры строку и число N и выдаёт список символов, которые
;встречаются в строке не менее N раз.
data segment para public 'data'
sNum db 'Enter N: $'
sString db 0ah,'Enter string: $'
sResult db 0ah,'Symbols: $'
;буфер для ввода числовой строки (для функции 0ah)
bNum db ? ;максимальный размер буфера
bCount db ? ;реальный размер строки
sBuf db 80 dup (?) ;сама строка
N dw ? ;"водораздел" количества символов
data ends
assume cs:code, ds:data, es:data
code segment para public 'code'
start:
mov ax, data
mov ds, ax
mov es, ax ;пусть es=ds=data
lea dx, sNum
mov ah, 9
int 21h ;ждем число N
mov bNum, 80 ;задаем максимальное значение строки
lea dx, bNum
mov ah, 0ah
int 21h ;вводим числовую строку
lea si, sBuf ;строка
call stoi ;преобразовываем в число
mov N, ax ;сохраним
lea dx, sString
mov ah, 9
int 21h ;ждем строку
lea dx, bNum
mov ah, 0ah
int 21h ;вводим строку
lea dx, sResult
mov ah, 9
int 21h ;выведем сообщение о результате
;формируем результат
lea si, sBuf ;адрес строки
xor cx, cx
mov cl, bCount ;длика строки
mov dx, cx ;сохраним для дальнейшего использования
AnalizeLoop: ;по всем символам строки
lodsb ;читаем al=ds:[si], si=si+1
cmp al, 0 ;0 помечается обработанный символ
je AnalizeNext ;обходим
call Analize ;считаем
cmp ax, N ;сравниваем с N
jc AnalizeNext ;если меньше, то обходим
mov al, [si-1] ;читаем заново символ
int 29h ;выводим
AnalizeNext:
loop AnalizeLoop ;по всем
mov ah, 0
int 16h ;ждем нажатия на клавишу
mov ax, 4c00h
int 21h ;выход в ДОС
Analize proc ;считаем вхожения символа в al в строку sBuf
push cx ;сохраним счетчик прохождения по строке
lea di, sBuf ;адрес строки
mov cx, dx ;длина
xor bx, bx ;счетчик
AnLoop:
scasb ;сравниваем al с es:[di], di=di+1
jne AnNext ;не равно - на следующий
test bx, bx ;проверим - первый найденный?
jz IncCnt ;если первый, то на инкремент количества
mov byte ptr [di-1], 0 ;все последующие обнуляем, чтобы не повторяться
IncCnt:
inc bx ;считаем
AnNext:
loop AnLoop
mov ax, bx ;найденное количество
pop cx
ret
Analize endp
stoi proc ;преобразование строки [si] в число AX
xor bx, bx ;здесь будем стоить число
xor cx, cx ;счетчик разрядов
stoi_next:
lodsb ;очередной символ
cmp al, 0dh ;конец стоки?
je stoi_eol
cmp al, '0'
jb stoi_sep ;любая нецифра - разделитель
cmp al, '9'
ja stoi_sep
push ax ;сохраним новый разряд
mov ax, 10
mul bx ;умножим старшие на 10
pop dx ;новый
and dx, 0fh ;'0'-'9' -> 0-9
add ax, dx ;добавляем новый разряд
mov bx, ax ;сохраняем
inc cx ;считаем
jmp stoi_next ;продолжаем
stoi_sep: ;встретили разделитель
jcxz stoi_next ;были только разделители - на продолжение
; иначе - конец числа и выходим
stoi_eol: ; если числа нет и встретили 0dh - конец строки
mov ax, bx ;число возвращаем в ax
ret
stoi endp
code ends
end start[/code]