我一直在研究这个程序,我必须输入一个字符串,然后在该字符串中显示字符分布。
例如:
如果输入是“minecode”,则输出应为
C - 1
O - 1
D - 1
E - 2
我 - 1
M - 1
N - 1
这是我尝试做的,但我真的不知道如何遍历循环并检查相似的字符,然后递增计数。汇编程序是在32位机器上运行的MASM 615。
.686
.MODEL flat, stdcall
.STACK
INCLUDE Irvine32.inc
.DATA
msg0 BYTE "Enter a string of characters: ",0
msg1 BYTE "Character Distribution: ",0
MainArray dword 10000 dup (?)
UniqueChar dword 10000 dup (?)
CharCount dword 10000 dup (?)
.CODE
MAIN PROC
lea edx, msg0
call WriteString
call dumpregs ; 1
call ReadString
mov MainArray, eax
call dumpregs ; 2
mov MainArray, ebx
call dumpregs ; 3
call CRLF
lea edx, msg1
call WriteString
call CharDist ; Calls the procedure
call dumpregs ; 5
exit
MAIN ENDP
CharDist PROC
mov ecx, lengthof MainArray
mov esi, OFFSET MainArray
L1:
; what to do here??
Loop L1:
CharDist ENDP
END MAIN
答案 0 :(得分:5)
一种可能的方法:创建256个计数器的数组,将其基地址存储在ebx
中,对于字符串中的每个字节,将该计数器的计数器从ebx
递增。然后,遍历您的计数器数组并打印非零计数。
你永远不会说这是一个以0
字节(C风格)终止的字符串,一个以其长度(Pascal样式)开头的字符串,还是一个长度作为第二个参数传入的字符串,但是这将决定何时终止循环。如果您正在寻找终止零,请测试您刚刚读取的字节,如果您计算特定数量的字节,请保留ecx
中剩余的字节数并进行测试。 (如果您想使用ecx
不为零,则有条件地进行分支的特殊说明。)
如果您将指针指向esi
中的字符串,则可以使用al
指令将下一个字节加载到lodsb
。或者,您可以从mov
开始[esi]
,然后inc esi
。如果在eax
中存储每个字节之前将al
清零,这将为您提供eax
中可用于计数器阵列的索引。
答案 1 :(得分:3)
其他可能的方法:
应该更容易理解,实际上它非常“人性化”#34;直截了当(就像你怎么用铅笔在纸上做的那样),所以我想知道你是怎么想出来的......你不应该只是试着理解它是如何工作的,而是试着弄清楚为什么你没有看到它,是什么让你感到困惑/阻挡。
for all letters of alphabet [A-Z] as "letter" {
counter = 0;
for all characters in input string as "char" {
if (letter ignore_case_equals char) ++counter;
}
if (0 < counter) {
display "letter - counter" and new line.
}
}
对于英文字母和短字符串,这可能实际上更快,例如3-5个字母(仅包含字母);比建议的计数排序,因为字母表是26个字符,计数表是256字节,所以256/26 = ~9。但是计数表将显示任何字符的计数,包括非字母字符,并且它在分支时也会减少。
还要注意,你是如何开始为提示/输入/等发出代码......你已经可以在Assembly中做的事情,避免未知。
我的确从几乎英文的算法描述开始。因为我不在乎,我知道在大会上写的东西(我已经知道,几乎任何东西:)),首先我想确定我知道我想要代码为我做什么以及什么样的数据我想要处理。然后我将命令CPU执行它,通过最终确定数据结构计划并将这些英语注释拆分为更简单和更简单的步骤,直到它们开始类似于指令,然后我在注释之间填写说明。
不要跳过本地语言推理阶段,如果你想出一些优雅的方法来组织数据或通过重复使用它的某些部分来减少算法步骤,它可以为你节省大量的代码工作。不是每个问题都有简短优雅的解决方案,但很多都有。