既然有很多解决方案,我将回答您问题的“批判”部分。一些注意事项:我已经修正了一些错字,并指出了我做错的地方。如果我错认为他们是错字,请在评论中提及它,然后我将解释发生的情况。我将指出您可能已经知道的几件事,所以请不要冒犯我。一些评论似乎有些挑剔,但我不知道您的旅行路线,因此必须假设您才刚刚起步。
CREATE function Palindrome (
@String Char
, @StringLength Int
, @n Int
, @Palindrome BIN
, @StringLeftLength Int
总是用char
或varchar
定义长度。亚伦· 伯特兰德( Aaron Bertrand)在这里深入讨论。他在谈论,varchar
但同样如此char
。varchar(255)
如果您只想要较短的字符串,或者可能varchar(8000)
需要较大的字符串甚至是,我会使用a varchar(max)
。 Varchar
是用于可变长度的字符串char
,仅用于固定的字符串。由于您不确定使用中传递的字符串的长度varchar
。此外,它是binary
不是bin
。
接下来,您不需要将所有这些变量都作为参数。在您的代码中声明它们。仅当您计划将其传入或传出时,才将其放入参数列表中。(您将在最后看到它的外观。)此外,您还有@StringLeftLength,但从不使用它。所以我不会宣布它。
我要做的下一件事是重新格式化一下,使一些事情变得显而易见。
BEGIN
SET @n=1
SET @StringLength = Len(@String) -- Missed an @
WHILE @StringLength - @n >1
IF Left(@String,@n)=Right(@String, @StringLength) -- More missing @s
SET @n = @n + 1 -- Another missing @
SET @StringLength = @StringLength - 1 -- Watch those @s :)
RETURN @Palindrome = 1 -- Assuming another typo here
ELSE
RETURN @Palindrome =0
END
如果您看一下我进行缩进的方式,您会注意到我有这个:
WHILE @StringLength - @n >1
IF Left(@String,@n)=Right(@String, @StringLength)
SET @n = @n + 1
这是因为喜欢WHILE
和IF
仅影响命令之后的第一行代码。如果要使用BEGIN .. END
多个命令,则必须使用一个块。因此,我们得到了解决:
WHILE @StringLength - @n > 1
IF Left(@String,@n)=Right(@String, @StringLength)
BEGIN
SET @n = @n + 1
SET @StringLength = @StringLength - 1
RETURN @Palindrome = 1
END
ELSE
RETURN @Palindrome = 0
您会注意到,我只在中添加了一个BEGIN .. END
块IF
。这是因为即使该IF
语句长了多行(甚至包含多个命令),它仍然是一个语句(包含在语句IF
的ELSE
部分中执行的所有内容)。
接下来,您都将遇到错误RETURNs
。您可以返回变量或文字。您不能设置变量并同时返回它。
SET @Palindrome = 1
END
ELSE
SET @Palindrome = 0
RETURN @Palindrome
现在我们陷入逻辑。首先让我指出您正在使用的LEFT
and RIGHT
函数很棒,但是它们将为您提供从请求的方向传入的字符数。假设您通过了“测试”一词。在第一遍中,您将获得此信息(除去变量):
LEFT('test',1) = RIGHT('test',4)
t = test
LEFT('test',2) = RIGHT('test',3)
te = est
显然,这不是您所期望的。您真的想substring
代替使用。子字符串不仅可以传递起点,还可以传递长度。这样您将获得:
SUBSTRING('test',1,1) = SUBSTRING('test',4,1)
t = t
SUBSTRING('test',2,1) = SUBSTRING('test',3,1)
e = s
接下来,仅在IF语句的一种情况下递增在循环中使用的变量。将变量增量完全拉出该结构。这将需要一个额外的BEGIN .. END
块,但是我确实要删除另一个块。
WHILE @StringLength - @n > 1
BEGIN
IF SUBSTRING(@String,@n,1) = SUBSTRING(@String, @StringLength,1)
SET @Palindrome = 1
ELSE
SET @Palindrome = 0
SET @n = @n + 1
SET @StringLength = @StringLength - 1
END
您需要更改WHILE
条件以允许进行最后的测试。
WHILE @StringLength > @n
最后但并非最不重要的一点是,如果字符数量奇数,我们现在不会测试最后一个字符。例如,如果使用“ ana”,n
则未经测试。很好,但是对我来说,我们需要考虑一个字母词(如果您希望将其视为正数)。因此,我们可以通过预先设置该值来实现。
现在我们终于有了:
CREATE FUNCTION Palindrome (@String varchar(255))
RETURNS Binary
AS
BEGIN
DECLARE @StringLength Int
, @n Int
, @Palindrome binary
SET @n = 1
SET @StringLength = Len(@String)
SET @Palindrome = 1
WHILE @StringLength > @n
BEGIN
IF SUBSTRING(@String,@n,1) = SUBSTRING(@String, @StringLength,1)
SET @Palindrome = 1
ELSE
SET @Palindrome = 0
SET @n = @n + 1
SET @StringLength = @StringLength - 1
END
RETURN @Palindrome
END
最后的评论。我通常是格式化的忠实拥护者。它确实可以帮助您了解代码的工作原理,并指出可能的错误。
编辑
正如Sphinxxx所说,我们在逻辑上仍然存在缺陷。一旦我们点击ELSE
并设置@Palindrome
为0,就没有意义继续了。实际上,那时我们可以做到RETURN
。
IF SUBSTRING(@String,@n,1) = SUBSTRING(@String, @StringLength,1)
SET @Palindrome = 1
ELSE
RETURN 0
鉴于我们现在仅@Palindrome
用于“仍然有可能是回文”,因此确实没有意义。我们可以摆脱该变量,仅在故障RETURN 0
和故障(RETURN 1
正响应)一直贯穿整个循环时,才将其逻辑切换为短路。您会注意到,这实际上在某种程度上简化了我们的逻辑。
CREATE FUNCTION Palindrome (@String varchar(255))
RETURNS Binary
AS
BEGIN
DECLARE @StringLength Int
, @n Int
SET @n = 1
SET @StringLength = Len(@String)
WHILE @StringLength > @n
BEGIN
IF SUBSTRING(@String,@n,1) <> SUBSTRING(@String, @StringLength,1)
RETURN 0
SET @n = @n + 1
SET @StringLength = @StringLength - 1
END
RETURN 1
END
LTRIM(RTRIM(...))
空格?