Puisqu'il existe un bon nombre de solutions, je vais suivre la partie «critique» de votre question. Quelques notes: j'ai corrigé quelques fautes de frappe et noté où je l'ai fait. Si je me trompe sur le fait qu'il s'agit d'une faute de frappe, mentionnez-le dans les commentaires et je vous expliquerai ce qui se passe. Je vais souligner plusieurs choses que vous savez peut-être déjà, alors ne vous en offrez pas si je le faisais. Certains commentaires peuvent sembler difficiles, mais je ne sais pas où vous en êtes dans votre voyage, alors supposez que vous débutez.
CREATE function Palindrome (
@String Char
, @StringLength Int
, @n Int
, @Palindrome BIN
, @StringLeftLength Int
TOUJOURS inclure la longueur avec une définition char
ou varchar
. Aaron Bertrand parle en détail ici . Il parle varchar
mais il en va de même char
. J'utiliserais un varchar(255)
pour cela si vous ne voulez que des cordes relativement courtes ou peut-être un varchar(8000)
pour les plus grandes ou même varchar(max)
. Varchar
est pour les chaînes de longueur variable char
est uniquement pour les chaînes fixes. Puisque vous n'êtes pas sûr de la longueur de la chaîne transmise en cours d'utilisation varchar
. Ce n'est binary
pas non plus bin
.
Ensuite, vous n'avez pas besoin de mettre toutes ces variables en tant que paramètres. Déclarez-les dans votre code. Ne mettez quelque chose dans la liste des paramètres que si vous prévoyez de le faire entrer ou sortir. (Vous verrez à quoi cela ressemble à la fin.) Vous avez également @StringLeftLength mais ne l'utilisez jamais. Je ne vais donc pas le déclarer.
La prochaine chose que je vais faire est de reformater un peu pour rendre certaines choses évidentes.
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 vous regardez la façon dont j'ai fait l'indentation, vous remarquerez que j'ai ceci:
WHILE @StringLength - @n >1
IF Left(@String,@n)=Right(@String, @StringLength)
SET @n = @n + 1
En effet, les commandes comme WHILE
et IF
n'affectent que la première ligne de code après elles. Vous devez utiliser un BEGIN .. END
bloc si vous voulez plusieurs commandes. Ainsi, nous obtenons:
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
Vous remarquerez que je n'ai ajouté qu'un BEGIN .. END
bloc dans le IF
. En effet, même si l' IF
instruction est longue de plusieurs lignes (et contient même plusieurs commandes), il s'agit toujours d'une seule instruction (couvrant tout ce qui est effectué dans IF
et les ELSE
parties de l'instruction).
Ensuite, vous obtiendrez une erreur après les deux RETURNs
. Vous pouvez renvoyer une variable OU un littéral. Vous ne pouvez pas définir la variable et la renvoyer en même temps.
SET @Palindrome = 1
END
ELSE
SET @Palindrome = 0
RETURN @Palindrome
Maintenant, nous sommes dans la logique. Permettez-moi d'abord de souligner que les fonctions LEFT
et que RIGHT
vous utilisez sont excellentes, mais elles vous donneront le nombre de caractères que vous transmettez dans la direction demandée. Supposons donc que vous ayez réussi le mot "test". Lors de la première passe, vous obtiendrez ceci (suppression des variables):
LEFT('test',1) = RIGHT('test',4)
t = test
LEFT('test',2) = RIGHT('test',3)
te = est
Évidemment, ce n'est pas ce que vous attendiez. Vous voudriez vraiment utiliser à la substring
place. La sous-chaîne vous permet de passer non seulement le point de départ mais la longueur. Vous obtiendrez donc:
SUBSTRING('test',1,1) = SUBSTRING('test',4,1)
t = t
SUBSTRING('test',2,1) = SUBSTRING('test',3,1)
e = s
Ensuite, vous incrémentez les variables que vous utilisez dans votre boucle uniquement dans une condition de l'instruction IF. Retirez complètement la variable incrémentée de cette structure. Cela va nécessiter un BEGIN .. END
bloc supplémentaire , mais j'arrive à supprimer l'autre.
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
Vous devez changer votre WHILE
condition pour permettre le dernier test.
WHILE @StringLength > @n
Et enfin et surtout, dans l'état actuel des choses, nous ne testons pas le dernier caractère s'il y a un nombre impair de caractères. Par exemple avec 'ana' le n
n'est pas testé. C'est bien, mais il me faut nous devons tenir compte d'un mot d'une seule lettre (si vous voulez qu'il compte comme un positif qui est). Nous pouvons donc le faire en définissant la valeur à l'avance.
Et maintenant, nous avons enfin:
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 dernier commentaire. Je suis un grand fan du formatage en général. Cela peut vraiment vous aider à voir comment fonctionne votre code et à signaler d'éventuelles erreurs.
modifier
Comme Sphinxxx l'a mentionné, nous avons encore un défaut dans notre logique. Une fois que nous avons touché le ELSE
et mis @Palindrome
à 0, il est inutile de continuer. En fait, à ce stade, nous pourrions juste RETURN
.
IF SUBSTRING(@String,@n,1) = SUBSTRING(@String, @StringLength,1)
SET @Palindrome = 1
ELSE
RETURN 0
Étant donné que nous n'utilisons maintenant que @Palindrome
pour "il est toujours possible que ce soit un palindrome", il n'y a vraiment aucun intérêt à l'avoir. Nous pouvons nous débarrasser de la variable et commuter notre logique en court-circuit en cas d'échec (le RETURN 0
) et RETURN 1
(une réponse positive) uniquement si cela se fait tout au long de la boucle. Vous remarquerez que cela simplifie quelque peu notre logique.
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(...))
espace blanc?