Como existe um número razoável de soluções, eu irei à parte "crítica" da sua pergunta. Algumas notas: Corrigi alguns erros de digitação e observei onde fiz. Se eu estiver errado sobre o erro de digitação, mencione-o nos comentários e explico o que está acontecendo. Vou apontar várias coisas que você já deve saber, então, por favor, não se ofenda se eu soubesse. Alguns comentários podem parecer exigentes, mas eu não sei onde você está em sua jornada, portanto, suponha que você está apenas começando.
CREATE function Palindrome (
@String Char
, @StringLength Int
, @n Int
, @Palindrome BIN
, @StringLeftLength Int
SEMPRE inclua o comprimento com a char
ou varchar
definition. Aaron Bertrand fala sobre isso em profundidade aqui . Ele está falando, varchar
mas o mesmo vale para char
. Eu usaria um varchar(255)
para isso se você quiser apenas cordas relativamente curtas ou talvez uma varchar(8000)
para cordas maiores ou até mesmo varchar(max)
. Varchar
é para cadeias de comprimento variável char
é apenas para cadeias fixas. Como você não tem certeza do comprimento da cadeia que está sendo passada em uso varchar
. Também é binary
não bin
.
Em seguida, você não precisa colocar todas essas variáveis como parâmetros. Declare-os dentro do seu código. Coloque apenas algo na lista de parâmetros se você planeja passá-lo para dentro ou para fora. (Você verá como isso fica no final.) Além disso, você tem @StringLeftLength, mas nunca o usa. Então, eu não vou declarar isso.
A próxima coisa que vou fazer é reformatar um pouco para deixar algumas coisas óbvias.
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
Se você olhar para o jeito que eu fiz o recuo, você perceberá que eu tenho isso:
WHILE @StringLength - @n >1
IF Left(@String,@n)=Right(@String, @StringLength)
SET @n = @n + 1
Isso ocorre porque comandos como WHILE
e IF
afetam apenas a primeira linha de código após eles. Você precisa usar um BEGIN .. END
bloco se desejar vários comandos. Então, corrigindo o que temos:
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
Você notará que eu adicionei apenas um BEGIN .. END
bloco no IF
. Isso IF
ocorre porque, embora a declaração tenha várias linhas (e até contenha vários comandos), ainda é uma única declaração (cobrindo tudo o que é executado nas partes IF
e nas ELSE
partes da declaração).
Em seguida, você receberá um erro após os dois RETURNs
. Você pode retornar uma variável OU um literal. Você não pode definir a variável e retorná-la ao mesmo tempo.
SET @Palindrome = 1
END
ELSE
SET @Palindrome = 0
RETURN @Palindrome
Agora estamos na lógica. Primeiro, deixe-me salientar que as funções LEFT
e que RIGHT
você está usando são ótimas, mas elas fornecem o número de caracteres que você passa da direção solicitada. Então, digamos que você passou na palavra "teste". Na primeira passagem, você obterá isso (removendo variáveis):
LEFT('test',1) = RIGHT('test',4)
t = test
LEFT('test',2) = RIGHT('test',3)
te = est
Obviamente, isso não é o que você esperava. Você realmente gostaria de usar substring
. Substring permite passar não apenas o ponto inicial, mas também o comprimento. Então você obteria:
SUBSTRING('test',1,1) = SUBSTRING('test',4,1)
t = t
SUBSTRING('test',2,1) = SUBSTRING('test',3,1)
e = s
Em seguida, você está incrementando as variáveis que você usa em seu loop apenas em uma condição da instrução SE. Puxe a variável incrementada para fora dessa estrutura completamente. Isso vai exigir um BEGIN .. END
bloco adicional , mas eu consigo remover o outro.
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
Você precisa alterar sua WHILE
condição para permitir o último teste.
WHILE @StringLength > @n
E por último, mas não menos importante, do jeito que está agora, não testamos o último caractere se houver um número ímpar de caracteres. Por exemplo, com 'ana', o n
não é testado. Tudo bem, mas, para mim, precisamos contabilizar uma única letra (se você quiser que isso seja positivo). Então, podemos fazer isso definindo o valor antecipadamente.
E agora finalmente temos:
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
Um último comentário. Eu sou um grande fã de formatação em geral. Pode realmente ajudar você a ver como seu código funciona e ajudar a apontar possíveis erros.
Editar
Como Sphinxxx mencionou, ainda temos uma falha em nossa lógica. Quando atingimos ELSE
e definimos @Palindrome
como 0, não faz sentido continuar. De fato, naquele ponto, poderíamos apenas RETURN
.
IF SUBSTRING(@String,@n,1) = SUBSTRING(@String, @StringLength,1)
SET @Palindrome = 1
ELSE
RETURN 0
Dado que agora estamos usando apenas @Palindrome
para "ainda é possível, isso é um palíndromo", não há realmente sentido em tê-lo. Podemos nos livrar da variável e mudar nossa lógica para um curto-circuito em caso de falha (a RETURN 0
) e RETURN 1
(uma resposta positiva) apenas se ela passar por todo o ciclo. Você notará que isso realmente simplifica um pouco nossa lógica.
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(...))
espaço em branco?