В строке определить самое первое длинное слово и количество элементов в нем - Assembler/MASM

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

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

Помогите пожалуйста. Решить задачку. Задание есть строка, определить самое первое длинное слово и количество элементов в нем.

Решение задачи: «В строке определить самое первое длинное слово и количество элементов в нем»

textual
Листинг программы
.686
.model flat, stdcall
option casemap :none
 
        include \masm32\include\windows.inc
 
        include \masm32\include\user32.inc
        include \masm32\include\kernel32.inc
        include \masm32\include\masm32.inc
 
        includelib \masm32\lib\user32.lib
        includelib \masm32\lib\kernel32.lib
        includelib \masm32\lib\masm32.lib
.data
        DelimChar       equ     ' '
        aszCrLf         db      0Dh, 0Ah, 0
        aszPrompt       db      'Введите строку:', 0Dh, 0Ah, 0
        aszMsgIntResult db      'Длина %d-го слова: %d', 0Dh, 0Ah, 0
        aszMsgResult1   db      0Dh, 0Ah, 'Самое первое длинное слово: ', 0
        aszMsgResult2   db      0Dh, 0Ah, 'Его длина: %d', 0
        aszPressLeftAlt db      0Dh, 0Ah, 0Dh, 0Ah, "Press Left Alt to exit", 0
.data?
        hConsoleOutput  HANDLE  ?
        hConsoleInput   HANDLE  ?
        WordsCount      dd      ?
        MaxLen          dd      ?
        MaxAddr         dd      ?
        BufLen          dd      ?
        Buffer          db      1024 dup(?)
        StringLen       dd      ?
        String          db      1024 dup(?)
.code
 
start   proc
 
        ; получение описателей ввода и вывода консоли
        invoke  GetStdHandle,   STD_INPUT_HANDLE
        mov     hConsoleInput,  eax
        invoke  GetStdHandle,   STD_OUTPUT_HANDLE
        mov     hConsoleOutput, eax
        ;очистка экрана
        invoke  ClearScreen
        ;преобразование кодировки символов кириллицы
        invoke  CharToOem,      ADDR aszPrompt, ADDR aszPrompt
        invoke  CharToOem,      ADDR aszMsgIntResult, ADDR aszMsgIntResult
        invoke  CharToOem,      ADDR aszMsgResult1, ADDR aszMsgResult1
        invoke  CharToOem,      ADDR aszMsgResult2, ADDR aszMsgResult2
        ;ввод исходных данных - строки
        invoke  WriteConsole, hConsoleOutput, ADDR aszPrompt,\
                LENGTHOF aszPrompt - 1, ADDR BufLen, NULL
        invoke  ReadConsole, hConsoleInput, ADDR String,\
                LENGTHOF String, ADDR StringLen, NULL
        lea     esi,    [String]        ;удаление из буфера
        add     esi,    [StringLen]     ;символов перевода строки
        mov     [esi-2],word ptr 0
        sub     [StringLen],    2
 
        ;поиск максимального по длине слова
        lea     esi,    [String]
        mov     ecx,    [StringLen]
        mov     [WordsCount],   0       ;счетчик найденных слов
        mov     edx,    0               ;длина слова максимальной длины
        mov     edi,    esi             ;адрес слова максимальной длины
        jecxz   @@Finish
        ;пропускаем все разделители
@@WhileDelimiter:
        mov     al,     [esi]
        cmp     al,     DelimChar
        jne     @@NewWord
        inc     esi
        loop    @@WhileDelimiter
 
        jecxz   @@Finish        ;если строка закончилась - выйти
        ;найдено новое слово
@@NewWord:
        mov     ah,     al      ;запомним 1-й символ слова
        mov     ebx,    esi     ;адрес начала текущего слова
        inc     [WordsCount]    ;увеличиваем счётчик слов на 1
        ;пропускаем все буквы слова до разделителя
@@WhileWord:
        mov     al,     [esi]
        cmp     al,     DelimChar
        je      @@Break
@@NoInc:
        inc     esi             ;переходим к следующему символу
        loop    @@WhileWord
@@Break:
        mov     eax,    esi
        sub     eax,    ebx
        cmp     eax,    edx     ;сравнение с длиной максимального слова
        cmova   edx,    eax
        cmova   edi,    ebx
        ;вывод промежуточных результатов
        pushad
        sub     esi,    ebx
        invoke  wsprintf, ADDR Buffer, ADDR aszMsgIntResult, [WordsCount], esi
        mov     [BufLen],       eax
        invoke  WriteConsole, hConsoleOutput, ADDR Buffer,\
                BufLen, ADDR BufLen, NULL
        popad
 
        jecxz   @@Finish
        jmp     @@WhileDelimiter
@@Finish:
        ;в этом месте в регистрах содержиться
        ;edi - адрес первого длинного слова
        ;edx - длина первого длинного слова
        mov     [MaxLen],       edx
        mov     [MaxAddr],      edi
 
        ;вывод результатов
        invoke  WriteConsole, hConsoleOutput, ADDR aszMsgResult1,\
                LENGTHOF aszMsgResult1 - 1, ADDR BufLen, NULL
        invoke  WriteConsole, hConsoleOutput, [MaxAddr],\
                [MaxLen], ADDR BufLen, NULL
        invoke  wsprintf, ADDR Buffer, ADDR aszMsgResult2, [MaxLen]
        mov     [BufLen],       eax
        invoke  WriteConsole, hConsoleOutput, ADDR Buffer,\
                BufLen, ADDR BufLen, NULL
 
        ;ожидание нажатия Left Alt
        invoke  WriteConsole, hConsoleOutput, ADDR aszPressLeftAlt,\
                LENGTHOF aszPressLeftAlt - 1, ADDR BufLen, NULL
        @@WaitForLAlt:
                invoke  GetAsyncKeyState, VK_LMENU
                and     eax,    8000h
        jz      @@WaitForLAlt
        ;завершение программы
        invoke  ExitProcess, 0
start   endp
 
end start

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

Код написан на ассемблере и выполняет следующие действия:

  1. Получает описатели стандартного ввода и вывода консоли.
  2. Очищает экран.
  3. Преобразует символы кириллицы в кодировке ANSI в OEM.
  4. Вводит строку от пользователя.
  5. Пропускает все символы новой строки и переводы строки.
  6. Ищет самое длинное слово в строке.
  7. Выводит промежуточные результаты на экран.
  8. Выводит самое длинное слово и его длину.
  9. Ожидает нажатия клавиши Left Alt для завершения программы.

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

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