В строке определить самое первое длинное слово и количество элементов в нем - 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
Объяснение кода листинга программы
Код написан на ассемблере и выполняет следующие действия:
- Получает описатели стандартного ввода и вывода консоли.
- Очищает экран.
- Преобразует символы кириллицы в кодировке ANSI в OEM.
- Вводит строку от пользователя.
- Пропускает все символы новой строки и переводы строки.
- Ищет самое длинное слово в строке.
- Выводит промежуточные результаты на экран.
- Выводит самое длинное слово и его длину.
- Ожидает нажатия клавиши Left Alt для завершения программы.