【问题标题】:Remove extra spaces from a string assembly从字符串程序集中删除多余的空格
【发布时间】:2016-11-11 19:24:45
【问题描述】:

从汇编考试中得到一些问题。它是这样的,给定字符串:

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

但我仍然在字符串的开头得到一个额外的空格。

【问题讨论】:

  • 为什么输出应该在第一个world和第二个hello之间包含一个空格,但在第一个hello之前或者在world#之间没有空格?我发现该计划的要求不清楚。
  • 对不起,如果不清楚,它会删除所有额外的空格,换句话说,输出字符串应该是这样的:“hello world hello world#”
  • 好吧,您的代码设计为总是留下一个空格。显然你想删除某些地方的所有空格(在字符串的开头/结尾?),所以你必须调整你的代码来处理它。
  • 我试过这个解决方案stackoverflow.com/a/38532219/6389176....
  • 就像我说的,该算法总是留下一个空格。如果您有不同的要求,那么您将不得不提出不同的算法。

标签: assembly x86-16


【解决方案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(因此将复制单词后的下一个空格)。

当找到'#' 时,它会扫描字符串末尾的尾随空格,并在最后一个非空格字符之后(或当字符串为空时)写入终止“#”。


在 cmets 中谈论我如何构建此算法以及如何无法确定当前单词是否是最后一个 - 给了我另一个想法,即如何处理字符串结尾。要缓存最后一个已知单词的结束位置,因此在到达源字符串的末尾后,我可以使用缓存的指针直接将终止符设置在正确的位置。变体 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 

【讨论】:

  • @2Stoned:当然是这样?问题是,您是否了解它的工作原理,以及它是否会给您一些新的编程思路。如果您对代码有任何疑问,请写在这里。
  • 知道了(cx 允许一个空格,并删除 trail clean # 之前的空格),谢谢!非常好的解决方案。
  • @2Stoned 是的,并且以 cx=0 开头,它会删除第一个单词前面的所有空格(或者如果字符串完全由空格字符组成),因此它不需要额外的循环一开始,主循环的逻辑就符合这个目的。您是否确定字符串中至少有一个非空格字符(从不为空),可以完全删除 bx 测试(非空格字符将始终停止尾随循环),但当前版本比较指针以检测字符串的开头是我能想到的最好的处理字符串,如"#"" #"
  • 对我来说非常优雅的算法:)
  • @2Stoned 我构建它的基本想法是“数据流,过滤掉不需要的数据”......不幸的是,无法确定单词后遇到的空格是否属于前面的尾随空格# (不能说单词是否是最后一个),所以它不是纯流处理,它必须追溯结束。在好处方面:如果您在非空格字符上将cx 设置为n,它将在单词之间保留“最多 n”个空格(如果源字符串中有这么多空格)。
猜你喜欢
  • 1970-01-01
  • 2011-08-05
  • 1970-01-01
  • 2013-07-20
  • 2013-06-03
  • 2018-11-10
相关资源
最近更新 更多