【问题标题】:How can I traverse a string character by character [closed]如何逐个字符遍历字符串[关闭]
【发布时间】:2015-05-19 13:00:30
【问题描述】:

我有一个 C 程序,它接收来自标准输入的字符串并将其传递给用 32 位 x86 程序集编写的函数,该函数必须执行以下操作:

  • 检查字符串是否仅由字母数字字符组成。
  • 如果上一个测试的答案是肯定的,则返回字符串原样
  • 如果有一些非字母数字字符,函数必须用空格删除它们。
  • 检查字符串中的每个字符后,函数必须返回不含非字母数字字符的字符串。

这里是该例程必须执行的示例:

"only 4lph4numeric chars"        INPUT
"only 4lph4numeric chars"        OUTPUT

"here*some*for$bidden_chars#"    INPUT
"here some for bidden chars"     OUTPUT

我是汇编新手,但我知道如何比较字符,我认为删除其中一个就足以用空格替换它。

真正的问题是我不知道如何逐个字符地遍历字符串;我读过一些关于lods 的文章,但我不明白如何使用它。

【问题讨论】:

  • 怎么样?很简单:1) 学习组装 2) 尝试去做 3) 如果你在尝试做的时候发现了问题,请在此处发布你尝试过的内容以及遇到的问题。如果您希望我们为您做这件事,那么抱歉,您来错地方了。
  • 您为什么要猜测是否应该用' ' 替换无效字符,或者结果字符串是否应该更短?如果您的示例输出正确,它确认您应该用空格替换而不是复制所有后续字符来填补空白。

标签: c string assembly x86


【解决方案1】:

这就是你的做法。下一个代码是使用 Visual Studio 2010 C++ 控制台项目编写的。首先是汇编部分,注意cmets,如何从栈中获取字符串的地址,如何访问字符,最重要的部分,如何删除不需要的字符:

.386
.model flat, C
.code
;-------------------------------------------------------
check_alphanum proc

;PRESERVE EBP, ESI.
  push ebp
  push esi

  mov  ebp, esp
  add  ebp, 12          ;GET PARAMETER'S ADDRESS.
  mov  esi, [ ebp ]     ;ESI POINTS TO ARRAY.
whil:
  mov  al, [ esi ]      ;GET CURRENT CHAR.
  cmp  al, 0            ;CHECK END OF ARRAY.
  je   finale           ;IF ( AL == 0 ) END OF STRING.

;CHECK IF CURRENT CHAR IS 0..9-A..Z-a..z.
  cmp  al, '0'
  jb   its_invalid      ;IF ( AL <  '0' ) INVALID.
  cmp  al, '9'
  jbe  its_valid        ;IF ( AL <= '9' ) VALID.
  cmp  al, 'A'
  jb   its_invalid      ;IF ( AL <  'A' ) INVALID.
  cmp  al, 'Z'
  jbe  its_valid        ;IF ( AL <= 'Z' ) VALID.
  cmp  al, 'a'
  jb   its_invalid      ;IF ( AL <  'a' ) INVALID.
  cmp  al, 'z'
  jbe  its_valid        ;IF ( AL <= 'z' ) VALID.
  jmp  its_invalid      ;INVALID BECAUSE AL > 'z'.

its_valid:
;NEXT CHAR TO PROCESS.
  inc  esi
  jmp  whil

its_invalid:
;DELETE CURRENT CHAR PUSHING ALL CHARS ONE PLACE TO THE LEFT.
  mov  edi, esi         ;EDI POINTS TO CURRENT CHAR TO DELETE.
  mov  ebx, esi         ;EBX ALSO POINTS TO CURRENT CHAR.
  inc  ebx              ;NOW EBX POINTS TO NEXT CHAR.
shifting_left:
  mov  al, [ ebx ]      ;AL = NEXT CHAR.
  mov  [ edi ], al      ;CURRENT CHAR REPLACED BY NEXT.
  cmp  al, 0
  je   end_shifting
  inc  edi
  inc  ebx
  jmp  shifting_left
end_shifting:

  jmp  whil             ;REPEAT PROCESS FOR NEXT CHAR.

finale:

;RESTORE EBP, ESI.
  pop  esi
  pop  ebp

  ret
check_alphanum endp
;-------------------------------------------------------
end

现在是 C++ 部分。以前的过程可以这样调用,例如,从“main”方法中调用:

extern "C" void check_alphanum ( char * arr );
...
char arr[] = "A213457B-3746DFA3-578EC20E-4567DFF2-08A1B3AC-7B125F3A";
check_alphanum( arr );

得到的字符串是:

"A213457B3746DFA3578EC20E4567DFF208A1B3AC7B125F3A"

下一张图片显示了项目树中外部程序集文件的位置:

您所要做的就是向您的项目添加一个新文件,随意命名,但使用“.asm”扩展名,将我的代码复制粘贴到其中,就可以使用(或准备好)打电话)。

【讨论】:

  • 为您删除的每个字符移动整个字符串的其余部分是 O(N^2)。保持指向当前读取位置和当前写入位置的指针将是 O(N)。即使您要以这种方式复制,如果它们之间的偏移量是常量,则不需要两个单独的指针。只需从[ebx + 1] 加载并存储到[ebx]
猜你喜欢
  • 2013-01-18
  • 1970-01-01
  • 2014-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-14
  • 2015-03-09
  • 2021-06-30
相关资源
最近更新 更多