Lisp回文检测函数问题排查:始终返回非回文结果如何修复?
修复你的Lisp回文判断函数
我帮你梳理下原代码里的几个关键问题,正是这些问题导致函数始终返回"Is not a palindrome":
1. 循环条件完全写反了
原代码里的(loop while (< j i) do ...),初始时i=0,j是字符串长度减1(比如字符串长度为5时j=4),这时候(< j i)就是(<4 0),结果是nil,循环直接不执行,bandera保持初始值0,自然会返回"Is not a palindrome"。正确的循环条件应该是(< i j)——当左指针还没超过右指针时继续检查。
2. 指针变量没有正确更新
你写的(+ i 1)和(- j 1)只是做了数值计算,但没有把结果赋值回i和j,这意味着循环里i和j的值永远不会变,即使条件写对了,也会进入死循环。必须用(setq i (+ i 1))和(setq j (- j 1))来更新指针。
3. 标志位(bandera)的逻辑混乱
原代码里的逻辑是:字符相等时设bandera=1,但紧接着又用unless判断字符不等时设bandera=0——这会导致只要最后一对字符不等,就会把之前的标记覆盖,而且即使中间有不等的字符,也不会提前终止循环,效率很低。正确的逻辑应该是:默认假设是回文(bandera=1),一旦发现某一对字符不等,立刻把bandera设为0并跳出循环,不需要再检查剩下的字符。
4. 局部变量的声明不规范
直接用setq声明变量会污染全局命名空间,最好用let来定义局部变量,这是Lisp的最佳实践。
修复后的代码
(defun palindromo (x) (let ((i 0) (j (- (length x) 1)) (bandera 1)) ; 默认假设是回文 (loop while (and (< i j) (= bandera 1)) do ; 只要指针没交叉且还是回文就继续 (if (char/= (char x i) (char x j)) (setq bandera 0) ; 发现不等,标记为非回文 (progn ; 字符相等,更新指针 (setq i (+ i 1)) (setq j (- j 1))))) (cond ((= bandera 0) (write "Is not a palindrome")) ((= bandera 1) (write "Is a palindrome")))))
额外优化建议
其实Lisp里有更简洁的写法,不需要手动操作指针,比如直接比较字符串和它的反转:
(defun palindromo (x) (if (string= x (reverse x)) (write "Is a palindrome") (write "Is not a palindrome")))
这种写法更符合Lisp的风格,也不容易出错。
内容的提问来源于stack exchange,提问作者Cinthia Lima
相关产品推荐
相关产品推荐

