Определить, есть ли в записи числа цифра, равная среднему арифметическому остальных цифр - Assembler (223113)

Узнай цену своей работы

Формулировка задачи:

Задано целое беззнаковое число Х<65536. Определить, есть ли в записи числа цифра, равная среднему арифметическому остальных цифр? Входное значение - число без знака длиной в слово – должно вводиться с клавиатуры. Результат работы – найденная цифра или соответствующее сообщение - необходимо вывести на экран. Обмен информацией с пользователем организовать в виде специальных сообщений, каждое из которых следует размещать в отдельной строке экрана.

Решение задачи: «Определить, есть ли в записи числа цифра, равная среднему арифметическому остальных цифр»

textual
Листинг программы
LOCALS
 
.model small
 
.stack 100h
 
.data
        X               dw      ?
 
        Prompt          db      'Input X: ', '$'
        Error01         db      'Input error number',0Dh, 0Ah, '$'
        msgFoundDigit   db      'Found Digit: '
        Digit           db      0
                        db      0Dh, 0Ah, '$'
        msgNotFound     db      'Not found', 0Dh, 0Ah, '$'
        CrLf            db      0Dh, 0Ah, '$'
 
        kbdBuf          db      6, 0, 6 dup(?)
 
.code
 
main    proc
        mov     ax,     @data
        mov     ds,     ax
 
        lea     si,     X
        lea     di,     Prompt
        call    InputUInt16
 
        ;вычисление суммы всех цифр и их количества в числе
        mov     ax,     X
        mov     bx,     0       ;bx=SumDigits - сумма цифр
        mov     cx,     0       ;cx=N - количество цифр
        mov     di,     10
@@CalcSum:
        mov     dx,     0       ;ax=Digit - очередная цифра
        div     di
        add     bx,     dx
        inc     cx
        or      ax,     ax
        jnz     @@CalcSum
 
        ;проверка каждой цифры на то, что она равна
        ;среднему арифметическому остальных цифр
        ;т.е. Digit*(N-1)==(SumDigits-Digit)
        mov     ax,     X       ;ax=X
        mov     di,     10
        dec     cx              ;cx=N-1
        mov     si,     0       ;количество найденных цифр
        jcxz    @@Result        ;если всего одна цифра в числе, то искать нечего
@@ForEachDigit:
        mov     dx,     0
        div     di
        push    ax
        push    bx
        sub     bx,     dx      ;bx=SumDigits-Digit
        mov     ax,     dx      ;ax=Digit*(N-1)
        add     dl,     '0'     ;перед затиранием от операции умножения значения в dx
        mov     Digit,  dl      ;сохраним очередную цифру в памяти в виде символа
        mul     cx
 
        cmp     ax,     bx      ;Digit*(N-1)==(SumDigits-Digit) ?
        jne     @@SkipShow
        inc     si              ;признак - цифра была найдена
        push    ax
        push    dx
        mov     ah,     09h
        lea     dx,     msgFoundDigit
        int     21h
        pop     dx
        pop     ax
@@SkipShow:
        pop     bx
        pop     ax
        or      ax,     ax
        jnz     @@ForEachDigit
@@Result:
        cmp     si,     0
        jnz     @@SkipMsg
        mov     ah,     09h
        lea     dx,     msgNotFound
        int     21h
@@SkipMsg:
 
        mov     ax,     4C00h
        int     21h
main    endp
;ввод числа с обработкой ошибок
; ds:si - адрес числа
; ds:di - адрес строки приглашения к вводу
InputUInt16     proc
        push    ax
        push    bx
        push    cx
        push    dx
        push    si
        push    di
 
@@Input:
        push    si
        push    di
        ; ввод числа с клавиатуры (строки)
        mov     ah,     09h
        mov     dx,     di
        int     21h
 
        mov     ah,     0Ah
        lea     dx,     [kbdBuf]
        int     21h
 
        ; перевод строки (на новую строку)
        mov     ah,     09h
        lea     dx,     [CrLf]
        int     21h
 
        pop     di
        pop     si
 
        ; преобразование строки в число
        push    si
        push    di
        mov     di,     si
        lea     si,     kbdBuf+1
        call    Str2Num
        pop     di
        pop     si
 
        ; проверка на ошибку
        jnc     @@NoError
 
        ; если есть ошибка ввода - напечатать сообщение об ошибке
        mov     ah,     09h
        lea     dx,     Error01
        int     21h
        jmp     @@Input
 
        ; если нет ошибки ввода - напечатать число
@@NoError:
        pop     di
        pop     si
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        ret
InputUInt16     endp
 
 
; преобразования строки в число
; на входе:
; ds:[si] - строка с числом
; ds:[di] - адрес числа
; на выходе
; ds:[di] - число
; CY - флаг переноса (при ошибке - установлен, иначе - сброшен)
Str2Num proc
        push    ax
        push    bx
        push    cx
        push    dx
        push    ds
        push    es
 
        push    ds
        pop     es
 
        mov     cl, ds:[si]
        xor     ch, ch
 
        inc     si
 
        mov     bx, 10
        xor     ax, ax
 
@@Loop:
        mul     bx         ; умножаем ax на 10 ( dx:ax=ax*bx )
        mov     [di], ax   ; игнорируем старшее слово
        cmp     dx, 0      ; проверяем, результат на переполнение
        jnz     @@Error
 
        mov     al, [si]   ; Преобразуем следующий символ в число
        cmp     al, '0'
        jb      @@Error
        cmp     al, '9'
        ja      @@Error
        sub     al, '0'
        xor     ah, ah
        add     ax, [di]
        jc      @@Error    ; Если сумма больше 65535
        inc     si
 
        loop    @@Loop
 
        mov     [di], ax
        clc
        pop     es
        pop     ds
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        ret
@@Error:
        xor     ax, ax
        mov     [di], ax
        stc
        pop     es
        pop     ds
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        ret
Str2Num endp
 
; выводит число из регистра AX на экран
; входные данные:
; ax - число для отображения
; cx - система счисления (не больше 10)
Show_AX proc
        push    ax
        push    bx
        push    cx
        push    dx
        push    di
 
        mov     cx, 10          ; cx - основание системы счисления
        xor     di, di          ; di - кол. цифр в числе
 
@@Conv:
        xor     dx, dx
        div     cx              ; dl = num mod 10
        add     dl, '0'         ; перевод в символьный формат
        inc     di
        push    dx              ; складываем в стэк
        or      ax, ax
        jnz     @@Conv
        ; выводим из стэка на экран
@@Show:
        pop     dx              ; dl = очередной символ
        mov     ah, 2           ; ah - функция вывода символа на экран
        int     21h
        dec     di              ; повторяем пока di<>0
        jnz     @@Show
 
        pop     di
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        ret
Show_AX endp
 
end     main

Объяснение кода листинга программы

  1. Инициализация переменных:
    • X - двухбайтовая переменная для хранения введенного числа
    • Prompt - строка для приглашения к вводу
    • Error01 - строка для сообщения об ошибке при вводе числа
    • msgFoundDigit - строка для сообщения о найденной цифре
    • Digit - переменная для хранения текущей проверяемой цифры
    • msgNotFound - строка для сообщения о том, что цифра не найдена
    • CrLf - строка для вывода новой строки на экран
    • kbdBuf - массив для хранения вводимого числа с клавиатуры
  2. Ввод числа с клавиатуры и обработка ошибок в InputUInt16
  3. Вычисление суммы всех цифр и их количества в числе
  4. Проверка каждой цифры на то, что она равна среднему арифметическому остальных цифр
  5. Вывод сообщений о найденных или не найденных цифрах
  6. Завершение программы.

Оцени полезность:

13   голосов , оценка 4.077 из 5
Похожие ответы