Como hay una buena cantidad de soluciones, voy a ir con la parte de "crítica" de su pregunta. Un par de notas: he corregido algunos errores tipográficos y anotado dónde lo hice. Si me equivoco acerca de que sean un error tipográfico, menciónelo en los comentarios y explicaré lo que está sucediendo. Voy a señalar varias cosas que quizás ya sepas, así que no te ofendas si lo supiera. Algunos comentarios pueden parecer exigentes, pero no sé dónde se encuentra en su viaje, así que debo asumir que recién está comenzando.
CREATE function Palindrome (
@String Char
, @StringLength Int
, @n Int
, @Palindrome BIN
, @StringLeftLength Int
SIEMPRE incluya la longitud con una char
o varchar
definición. Aaron Bertrand habla en profundidad aquí . Él está hablando varchar
pero lo mismo ocurre char
. Usaría un varchar(255)
para esto si solo desea cadenas relativamente cortas o tal vez un varchar(8000)
para las más grandes o incluso varchar(max)
. Varchar
es para cadenas de longitud variablechar
es solo para fijas. Dado que no está seguro de la longitud de la cadena que se pasa en uso varchar
. También es binary
nobin
.
A continuación, no necesita poner todas esas variables como parámetros. Declararlos dentro de su código. Solo ponga algo en la lista de parámetros si planea pasarlo dentro o fuera. (Verá cómo se ve esto al final). También tiene @StringLeftLength pero nunca lo usa. Entonces no lo voy a declarar.
Lo siguiente que voy a hacer es volver a formatear un poco para que algunas cosas sean obvias.
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
Si observa la forma en que hice la sangría, notará que tengo esto:
WHILE @StringLength - @n >1
IF Left(@String,@n)=Right(@String, @StringLength)
SET @n = @n + 1
Esto se debe a que los comandos como WHILE
y IF
solo afectan la primera línea de código después de ellos. Tienes que usar un BEGIN .. END
bloque si quieres múltiples comandos. Entonces arreglando eso obtenemos:
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
Notarás que solo agregué un BEGIN .. END
bloque en el IF
. Esto se debe a que aunque la IF
declaración tiene varias líneas de largo (e incluso contiene múltiples comandos), sigue siendo una sola declaración (que cubre todo lo realizado en el IF
y elELSE
partes de la declaración).
A continuación, recibirá un error después de ambos RETURNs
. Puede devolver una variable O un literal. No puede establecer la variable y devolverla al mismo tiempo.
SET @Palindrome = 1
END
ELSE
SET @Palindrome = 0
RETURN @Palindrome
Ahora estamos en la lógica. Primero permítanme señalar que las funciones LEFT
y RIGHT
que está utilizando son excelentes, pero le darán la cantidad de caracteres que pasa desde la dirección solicitada. Digamos que aprobaste la palabra "prueba". En la primera pasada obtendrá esto (eliminando variables):
LEFT('test',1) = RIGHT('test',4)
t = test
LEFT('test',2) = RIGHT('test',3)
te = est
Obviamente eso no es lo que esperabas. Realmente querrás usar substring
en su lugar. La subcadena le permite pasar no solo el punto de partida sino también la longitud. Entonces obtendrías:
SUBSTRING('test',1,1) = SUBSTRING('test',4,1)
t = t
SUBSTRING('test',2,1) = SUBSTRING('test',3,1)
e = s
A continuación, está incrementando las variables que usa en su ciclo solo en una condición de la instrucción IF. Extraiga la variable incremental de esa estructura por completo. Eso requerirá un BEGIN .. END
bloqueo adicional , pero puedo eliminar el otro.
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
Necesita cambiar su WHILE
condición para permitir la última prueba.
WHILE @StringLength > @n
Y por último, pero no menos importante, tal como está ahora, no probamos el último carácter si hay un número impar de caracteres. Por ejemplo con 'ana' eln
no se prueba. Eso está bien, pero me hace falta que tengamos en cuenta una palabra de una sola letra (si quieres que cuente como algo positivo). Entonces podemos hacerlo estableciendo el valor por adelantado.
Y ahora finalmente tenemos:
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
Un ultimo comentario. Soy un gran fanático del formato en general. Realmente puede ayudarlo a ver cómo funciona su código y ayudarlo a señalar posibles errores.
Editar
Como mencionó Sphinxxx, todavía tenemos una falla en nuestra lógica. Una vez que tocamos ELSE
y establecemos @Palindrome
en 0, no tiene sentido continuar. De hecho, en ese momento podríamos simplemente RETURN
.
IF SUBSTRING(@String,@n,1) = SUBSTRING(@String, @StringLength,1)
SET @Palindrome = 1
ELSE
RETURN 0
Dado que ahora solo estamos usando @Palindrome
para "todavía es posible que esto sea un palíndromo", realmente no tiene sentido tenerlo. Podemos deshacernos de la variable y cambiar nuestra lógica a cortocircuito en caso de falla (la RETURN 0
) y RETURN 1
(una respuesta positiva) solo si logra pasar por todo el bucle. Notarás que esto realmente simplifica un poco nuestra 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(...))
espacio en blanco?