проще (короче точно) алгоритм (?):
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
Почему выход содержит пробел между первым 'world' и второй' hello', но без пробелов перед первым 'hello' или между' world' и '' #? Я считаю, что требования к программе не ясны. – Michael
им жаль, если это не понятно, предположим, что нужно удалить все лишние пробелы, другими словами, строка вывода должна выглядеть так: «hello world hello world #» – 2Stoned
Ну, ваш код призван всегда оставлять одно место позади. Очевидно, вы хотите удалить все пробелы в некоторых местах (в начале/конце строки?), Поэтому вам придется настроить код для его обработки. – Michael