【发布时间】:2017-03-28 00:22:05
【问题描述】:
Palindromic 是一个可以双向读取的字符串。比如“雷达”、“哇”等
从 C 中我们知道,我们可以使用“for”循环和“if”表达式检查给定的字符串:
for(i=0; i<length; i++)
if(str[i] == str[length-i-1])
printf("Palindromic");
else
print("Non Palindromic");
这样我们就可以从两边到达字符串的中心。
这段代码需要我们统计过字符数才能知道字符串的长度。
在 MIPS 上,这个“for”循环似乎相当复杂。
这是我自己的地方:
.data
str: .space 20
isntpal: .asciiz "it is not palindromic!"
ispal: .asciiz "it is palindromic!"
.text
.globl main
main:
add $t0, $zero, $zero #t0 = i counter for the loops
add $t1, $zero, $zero #t1 = j counter for length of the string
li $v0, 8 #gets(str)
la $a0, str
la $a1, 20
syscall
length:
lb $s0, str($t0) #load each character to s0
beq $s0, '\0', NEXTCHECK
add $t0, $t0, 1 #i++ to scan all the characters of the string
add $t1, $t1, 1 #j++ for the total length of the string
j length
NEXTCHECK:
add $t0, $zero, $zero #clean the t0 register from the length loop
pal:
sub $t4, $t1, $t0 #length - i - 1
sub $t4, $t4, 1
lb $s0, str($t0) #str[i]
lb $s1, str($t4) #str[length-i-1]
slt $t3, $t0, $t1 #for(i=0; i<length; i++)
beq $t3, $zero, EXIT
add $t0, $t0, 1 #i++
beq $s0, $s1, ELSE #if (str[i] == str[length-i-1])
li $v0, 4 #printf("It is palindromic");
la $a0, ispal
syscall
j EXIT
ELSE:
li $v0, 4 #else printf("It is not palindromic");
la $a0, isntpal
syscall
j EXIT
j pal
EXIT:
li $v0, 10
syscall
我无法理解应该在哪里设置 EXIT 和 ELSE 标签,我认为这就是为什么它总是返回字符串是回文的,即使不是。
放置标签的正确方法是什么?
它需要多个标签吗?
【问题讨论】:
-
i不需要一直到length-1。有两个指针,一个从str开始,另一个从str+length-1开始。然后使用这两个指针读取一对字符,并比较字符。如果字符不相等,则字符串不是回文。如果字符相等,则增加第一个指针并减少第二个指针。如果现在第一个指针大于第二个,则字符串是回文并且你完成了,否则你继续。 -
如果第一个指针大于或等于第二个指针,它是回文 - 对于奇数长度的字符串,这将提前 1 个字符退出,而不是测试
(str[middle] == str[middle])。 -
@Michael 听起来更复杂,我的大脑快要烤熟了。
-
@Ped7g 我该如何改变呢?
-
首先在抽象级别清理你的算法步骤,例如检查你的
length计算,你有相同的值$t0和$t1,整个循环。一个用作索引,另一个用作长度计数器。如果你先在更高的层次上看它,你可能会意识到它们是平等的,只需要其中一个。通过类似的方式,您可以生成更短的 asm 程序。如果你只是写下你得到的第一个想法,你可能会得到很多重复的代码,比如在代码末尾显示字符串。如果您将a0设置为想要的字符串,则可以使用单个代码路径显示并退出