
Отчет по чему-то
.docМИХЕЙ
А6. выделить подстроку заключенную между (самыми внешними) круглыми скобками.
Разместить символы подстроки в обратном порядке и найти ее длину,а также
номера позиций внешнимих круглых скобок.
(*строка пуста*,*в строке нет открывающей круглой скобки*,
*в строке нет закрывающей круглой скобки*,*порядок скобок перепутан*)
A6VMIXEY.C
#include <stdio.h>
#include <windows.h>
#define MAX_SIZE 100 /* Предельная длина строки */
UINT ParseString( LPSTR, LPSTR, UINT*, UINT* );
INT user_errno;
CHAR old_str[MAX_SIZE];
CHAR new_str[MAX_SIZE];
static CHAR* message[]={ "Строка пуста",
"в строке нет открывающей круглой скобки",
"в строке нет закрывающей круглой скобки",
"порядок скобок перепутан"};
int main(int argc, char** argv)
{
CHAR text[MAX_SIZE];
UINT substring_len;
UINT first_bracket_pos;
UINT last_bracket_pos;
FILE* fp;
user_errno = 0;
CharToOem("Введите строку", text);
puts(text);
gets(old_str);
if( argc > 1 )
{
if ( (fp = fopen(argv[1], "a")) == NULL )
{
CharToOem("Невозможно открыть файл %s\n", text);
fprintf(stderr, text, argv[1]);
return 1;
}
CharToOem("Строка: %s\n", text);
fprintf( fp, text, old_str );
}
substring_len = ParseString( old_str, new_str, &first_bracket_pos, &last_bracket_pos );
if( !user_errno )
{
CharToOem( "\nНовая строка: %s\nПозиции скобок ( и ): %u %u\nДлина подстроки %u\n\n", text );
printf( text, new_str, first_bracket_pos, last_bracket_pos, substring_len );
if( argc > 1)
{
fprintf( fp, text, new_str, first_bracket_pos, last_bracket_pos, substring_len );
fclose( fp );
}
getchar();
return 0;
}
else
{
puts("\n");
CharToOem( message[ user_errno - 1], text);
puts(text);
if( argc > 1)
{
CharToOem("Ошибка: ", text);
fputs(text, fp);
CharToOem(message[ user_errno - 1], text);
fputs(text, fp);
fputs("\n\n", fp);
fclose(fp);
}
getchar();
return user_errno;
}
}
A6VMIXEY.asm
.386
.MODEL flat,C
EXTRN user_errno: SDWORD
PUBLIC ParseString
.CODE
;-----------------------------------------------------------;
; Процедура обработки строки ;
; ВХОД ;
; old_str - указатель на исходную строку ;
; new_str - указатель на место под новую строку ;
; first_br_pos - указатели на переменные в которые ;
; last_br_pos будут записаны позиции скобок ;
; ВЫХОД: ;
; EAX( возвращаемое значение ) - длина строки между ;
; внешними скобками ;
; Рабочие( используемые ) регистры: ;
; ECX - счётчик ;
; EDX - длина строки ;
; EDI - адрес исходной строки ;
; ESI - адрес новой (под)строки ; ;
; BL - позиция первой/последней скобки ( ( временно ) ;
; BH - позиция первой/последней скобки ) ( временно ) ;
;-----------------------------------------------------------;
ParseString PROC C old_str:DWORD, new_str:DWORD, \
first_br_pos:DWORD, last_br_pos:DWORD
LOCAL str_len ; Длина строки
LOCAL first_br ; Позиция первой скобки
LOCAL last_br ; Позиция последней скобки
cld ; Поиск в направлении возрастания адресов
; Определение длины строки
mov ecx, -1 ; В ECX - максимальное беззнаковое целое
mov edi, old_str ; В EDI - адрес строки
mov al, 0 ; В AL - терминатор строки
repne scasb ; Поиск конца строки
not ecx ; В ECX -
dec ecx ; длина строки
test ecx, ecx ; Если ECX = 0
jz err1 ; - на err1
mov str_len, ecx ; Сохраняем длину строки
; Поиск первых скобок
; Поиск первой скобки (
mov edi, old_str ; В EDI - адрес строки
mov al, '(' ; Символ для поиска
mov ecx, str_len ; Длина строки
repne scasb ; Ищем
jne err2 ; Если ZF=0, то символ ( не найден
mov bl, cl ; Сохраняем позицию найденного символа
; Поиск первой скобки )
mov edi, old_str ; Берём адрес строки
mov al, ')' ; Символ для поиска
mov ecx, str_len ; Длина строки
repne scasb ; Ищем
jne err3 ; Если ZF=0, т осимвол ) не найден
mov bh, cl ; Сохраняем позицию найденного символа
cmp bh, bl ; Сравниваем позиции первых скобок
jg err4 ; Если первая скобка ) то порядок скобок перепутан
mov ah, bl ; Сохраняем в AH позицию первой скобки
; Поиск последних скобок
std ; Теперь ищем с конца
; Поиск последней скобки (
mov edi, old_str ; Вычисляем
add edi, str_len ; указатель
dec edi ; на конец строки
mov al, '(' ; Символ для поиска
mov ecx, str_len ; Длина строки
repne scasb ; Ищем
jne err2 ; Если ZF=0, то символ ( не найден
mov bl, cl ; Сохраняем позицию найденного символа
; Поиск последней скобки )
mov edi, old_str ; Вычисляем
add edi, str_len ; указатель
dec edi ; на конец строки
mov al, ')' ; Символ для поиска
mov ecx, str_len ; Длина строки
repne scasb ; Ищем
jne err3 ; Если ZF=0, т осимвол ) не найден
mov bh, cl ; Сохраняем позицию найденного символа
cmp bh, bl ; Сравниваем позиции последних скобок
jl err4 ; Если последняя скобка ( то порядок скобок перепутан
; Подготовка к копированию
movzx eax, ah ; Расширяем до 32 бит
mov edx, str_len ; Вычисляем и сохраняем
sub edx, eax ; позицию
mov first_br, edx ; первой скобки
movzx eax, bh ; Расширяем до 32 бит
inc eax ; Вычисляем и сохраняем позицию
mov last_br, eax ; последней скобки
cld ; Копируем строку слева направо
; Копируем начало строки
mov ecx, first_br ; Берём длину первого куска
mov esi, old_str ; Откуда копировать
mov edi, new_str ; Куда копировать
rep movsb ; Копируем
; Копируем подстроку между скобками в обратном порядке
mov ecx, last_br ; Вычисляем
sub ecx, first_br ; длину подстроки
dec ecx ; между скобками
add edi, ecx ; Устанавливаем указатель
dec edi ; на конец подстроки
r_cpy:
lodsb ; Загружаем символ в AL
std ; Сохранять будем в обратном порядке
stosb ; Сохраняем
cld ; Меняем направление
loop r_cpy ; Повторяем для всей подстроки
; Копируем конец строки
mov ecx, str_len ; Вычисляем длину куска
sub ecx, last_br ; начиная с последней
inc ecx ; скобки
mov edi, new_str ; Вычисляем
add edi, last_br ; куда
dec edi ; копировать
rep movsb ; Копируем
; Закончили копировать
mov esi, first_br_pos ; Берём адрес переменной
mov eax, first_br ; Берём позицию первой скобки
mov [esi], eax ; Сохраняем
mov esi, last_br_pos ; Берём адрес переменной
mov eax, last_br ; Берём позицию последней скобки
mov [esi], eax ; Сохраняем в неё позицию последней скобки
mov eax, last_br ; Оставляем в EAX
sub eax, first_br ; размер
dec eax ; подстроки
ret
IRPC I,1234
err&I: mov user_errno, I
ret
ENDM
ParseString ENDP
END
protocol.txt
Строка: bweyfgwejfg
Ошибка: в строке нет открывающей круглой скобки
Строка: fewufg(fhiuwffue
Ошибка: в строке нет закрывающей круглой скобки
Строка: efhiwue(kfuehwifu(hfeuwf
Ошибка: в строке нет закрывающей круглой скобки
Строка: fhewfh(fjief)()()fjeifj(feif
Ошибка: порядок скобок перепутан
Строка: efuie(fefowfho)fjeoifwi
Новая строка: efuie(ohfwofef)fjeoifwi
Позиции скобок ( и ): 6 15
Длина подстроки 8
Строка: ()))()(()()(()())
Новая строка: ()()(()()(()())))
Позиции скобок ( и ): 1 17
Длина подстроки 15
размер кода программы
Start Length Name Class
0002:00000000 00014e89H .text CODE
адрес переменной user_errno
из карты памяти
Address Publics by Value Rva+Base Lib:Object
0004:000018f4 _user_errno 0042b8f4 <common>
из дебаггера
&user_errno 0x0042b8f4 _user_errno int *
стековый кадр
ESP 0x0012FD40 00000007 - last_br
EBP-8 0x0012FD44 00000003 - first_br
EBP-4 0x0012FD48 0000000b - str_len
EBP 0x0012FD4C 0012fedc - старое EBP
EBP+4 0x0012FD50 00411c44 - адрес возврата из ParseString
EBP+8 0x0012FD54 0042b900 - old_str
EBP+C 0x0012FD58 0042b860 - new_str
EBP+10 0x0012FD5C 0012fe5c - first_br_pos
EBP+14 0x0012FD60 0012fe50 - last_br_pos