2016-11-10 6 views
0

Получил некоторый вопрос от экзамена в сборке. Это происходит следующим образом: строкаУдалить лишние пробелы со сборки строки

str db " hello world hello world #" 

Знак # указывает на конец строки. После манипуляции строка должна выглядеть так:

"hello world hello world#" 

Любой алгоритм или совет для удаления лишнего пробела будут оценены.

Я попробовал этот код:

data segment 
str db " hello world hello world #" data ends  


start: 
mov si,offset str 
mov di,0 

while: 
cmp [si],'#' 
jne loopwhile 
jmp whileT 
loopwhile: 
inc di 
inc si 
jmp while 

whileT: 
mov si,0 
while2: 
cmp si,di 
jae finish 

    cmp str[si],32 
    je check2 
    inc si 
    jmp while2 
    check2: 
    cmp str[si+1],32 
    je inner 
    inc si 
    jmp while2 
     inner: 
     mov bx,si 
     inc bx 
     innerW: 
     cmp bx,di 
     jae finishInner 
     mov al,str[bx+1] 
     mov str[bx],al 
     inc bx 
     jmp innerW 
     finishInner: 
     dec di 
     jmp while2 

finish: 
mov ax,4Ch 
int 21h 

code ends 

, но до сих пор я получаю одно дополнительное место в начале строки.

+0

Почему выход содержит пробел между первым 'world' и второй' hello', но без пробелов перед первым 'hello' или между' world' и '' #? Я считаю, что требования к программе не ясны. – Michael

+0

им жаль, если это не понятно, предположим, что нужно удалить все лишние пробелы, другими словами, строка вывода должна выглядеть так: «hello world hello world #» – 2Stoned

+0

Ну, ваш код призван всегда оставлять одно место позади. Очевидно, вы хотите удалить все пробелы в некоторых местах (в начале/конце строки?), Поэтому вам придется настроить код для его обработки. – Michael

ответ

1

проще (короче точно) алгоритм (?):

mov ax,SEG str 
    mov ds,ax 
    mov es,ax 
    mov si,OFFSET str 
    mov di,si 
    mov bx,si 
    ; ds:si = source pointer to read char by char 
    ; es:di = destination pointer to write modified string 
    ; bx = str pointer for compare during second phase 
    xor cx,cx ; cx = 0, counts spaces to copy 

copyLoop: 
    lodsb   ; al = ds:[si++] 
    cmp al,'#' 
    je removeTrailingSpaces 
    cmp al,' ' 
    jne notSpace 
    jcxz copyLoop ; no more spaces allowed to copy, skip 
    ; copy the space 
    dec cx  ; --allowed 
    stosb   ; es:[di++] = al 
    jmp copyLoop 

notSpace: 
    mov cx,1  ; one space can be copied next time 
    stosb   ; copy the not-space char 
    jmp copyLoop 

removeTrailingSpaces: 
    cmp di,bx 
    je emptyStringResult 
    dec di 
    cmp BYTE PTR [di],' ' 
    je removeTrailingSpaces 
    inc di  ; not-space found, write '#' after it 
emptyStringResult: 
    stosb   ; write the '#' at final position 

    mov ax,4Ch ; exit 
    int 21h 

Как это работает:

просто копирует почти все из ds:[si] в es:[di], кол-Даунс пространства и пропускает их, когда счетчик равен нулю , Непространственный символ сбрасывает счетчик на 1 (так что следующее пространство после слова будет скопировано).

Когда найдено '#', он сканирует конец строки для конечных пробелов и записывает завершение «#» после последнего непространственного символа (или когда строка пуста).


Говоря в комментариях о том, как я построил этот алгоритм и как это не представляется возможным, чтобы решить, является ли текущее слово является последним, - дал мне еще одну идею, как иметь дело с концом строки. Для кэширования последней известной конечной позиции слова, поэтому, после достижения конца строки источника, я могу использовать кешированный указатель, чтобы напрямую установить терминатор в правильном месте. Вариант 2:

; initial code is identical, only function of bx is different, so updated comment: 
    ... 
    ; bx = str pointer pointing +1 beyond last non-space character 
    ; (for empty input string that means OFFSET str to produce "#" result) 
    ... 

copyLoop: 
    lodsb   ; al = ds:[si++] 
    cmp al,'#' 
    je setTerminatorAndExit 
    cmp al,' ' 
    jne notSpace 
    jcxz copyLoop ; no more spaces allowed to copy, skip 
    ; copy the space 
    dec cx  ; --allowed 
    stosb   ; es:[di++] = al 
    jmp copyLoop 

notSpace: 
    mov cx,1  ; one space can be copied next time 
    stosb   ; copy the not-space char 
    mov bx,di  ; update bx to point +1 beyond last non-space char 
    jmp copyLoop 

setTerminatorAndExit: 
    mov [bx],al ; write the '#' to cached position of last non-space+1 

    mov ax,4Ch ; exit 
    int 21h 
+0

Спасибо, работа! – 2Stoned

+0

@ 2Stoned: Конечно? Вопрос в том, понимаете ли вы, как это работает, и если оно даст вам несколько новых идей для вашего собственного программирования. Если у вас есть вопрос о коде, напишите его здесь. – Ped7g

+0

Yap получил (cx разрешает одно место и удаляет след, очищая пространство до #), спасибо! очень приятное решение. – 2Stoned