Ponieważ istnieje spora liczba rozwiązań, przejdę do części „krytyki” twojego pytania. Kilka uwag: Naprawiłem kilka literówek i zauważyłem, gdzie to zrobiłem. Jeśli się mylę, że są literówką, wspomnij o tym w komentarzach, a wyjaśnię, co się dzieje. Mam zamiar wskazać kilka rzeczy, które być może już wiesz, więc proszę, nie obrażaj się, jeśli to zrobię. Niektóre komentarze mogą wydawać się wybredne, ale nie wiem, gdzie jesteś w podróży, więc musisz założyć, że dopiero zaczynasz.
CREATE function Palindrome (
@String Char
, @StringLength Int
, @n Int
, @Palindrome BIN
, @StringLeftLength Int
ZAWSZE uwzględniaj długość z definicją charlub varchar. Aaron Bertrand mówi tutaj dogłębnie . Mówi, varcharale to samo dotyczy char. Użyłbym varchar(255)do tego, jeśli chcesz tylko stosunkowo krótkich łańcuchów, a może varchar(8000)dla większych, a nawet varchar(max). Varcharjest dla ciągów o zmiennej długości charjest tylko dla stałych. Ponieważ nie jesteś pewien długości przekazywanego ciągu w użyciu varchar. Także to binarynie bin.
Następnie nie musisz umieszczać wszystkich tych zmiennych jako parametrów. Zadeklaruj je w swoim kodzie. Umieść coś na liście parametrów tylko, jeśli planujesz przekazać lub wyrzucić. (Zobaczysz, jak to wygląda na końcu.) Również masz @StringLeftLength, ale nigdy go nie używaj. Więc nie zamierzam tego deklarować.
Następną rzeczą, którą zamierzam zrobić, jest ponowne sformatowanie, aby kilka rzeczy było oczywistych.
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
Jeśli spojrzysz na sposób, w jaki zrobiłem wcięcie, zauważysz, że mam to:
WHILE @StringLength - @n >1
IF Left(@String,@n)=Right(@String, @StringLength)
SET @n = @n + 1
Jest tak, ponieważ polecenia takie jak WHILEi IFwpływają tylko na pierwszy wiersz kodu po nich. Musisz użyć BEGIN .. ENDbloku, jeśli chcesz mieć wiele poleceń. Naprawiając to, otrzymujemy:
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
Zauważysz, że dodałem tylko BEGIN .. ENDblok w IF. To dlatego, mimo że IFoświadczenie jest wiele linii długo (a nawet zawiera wiele poleceń) jest jeszcze jedno sprawozdanie (obejmujące wszystko wykonywane w IFa ELSEczęściami rachunku).
Następnie pojawi się błąd po obu RETURNs. Możesz zwrócić zmienną LUB literał. Nie można ustawić zmiennej i zwrócić jej jednocześnie.
SET @Palindrome = 1
END
ELSE
SET @Palindrome = 0
RETURN @Palindrome
Teraz jesteśmy w logice. Po pierwsze, pozwól mi zaznaczyć, że funkcje LEFTi RIGHT, których używasz, są świetne, ale podadzą ci liczbę znaków przekazywanych z żądanego kierunku. Powiedzmy, że zdałeś słowo „test”. Przy pierwszym przejściu dostaniesz to (usuwanie zmiennych):
LEFT('test',1) = RIGHT('test',4)
t = test
LEFT('test',2) = RIGHT('test',3)
te = est
Oczywiście nie tego się spodziewałeś. Naprawdę chcesz użyć substringzamiast tego. Podciąg pozwala przekazać nie tylko punkt początkowy, ale także długość. Otrzymasz więc:
SUBSTRING('test',1,1) = SUBSTRING('test',4,1)
t = t
SUBSTRING('test',2,1) = SUBSTRING('test',3,1)
e = s
Następnie zwiększasz zmienne używane w pętli tylko w jednym warunku instrukcji IF. Całkowicie wyciągnij zmienną inkrementację z tej struktury. Będzie to wymagało dodatkowego BEGIN .. ENDbloku, ale mogę usunąć drugi.
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
Musisz zmienić swój WHILEstan, aby umożliwić ostatni test.
WHILE @StringLength > @n
I na koniec, tak jak teraz, nie testujemy ostatniego znaku, jeśli liczba znaków jest nieparzysta. Na przykład z „ana” nnie jest testowany. W porządku, ale to do mnie należy, że musimy uwzględnić jedno literowe słowo (jeśli chcesz, aby było liczone jako pozytywne). Możemy to zrobić, ustawiając wartość z góry.
A teraz w końcu mamy:
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
Ostatni komentarz. Ogólnie jestem wielkim fanem formatowania. To naprawdę może ci pomóc zobaczyć, jak działa twój kod i pomóc wskazać możliwe błędy.
Edytować
Jak wspomniał Sphinxxx, nadal mamy wadę w naszej logice. Po trafieniu ELSEi ustawieniu @Palindromena 0 nie ma sensu kontynuować. W tym momencie moglibyśmy właśnie RETURN.
IF SUBSTRING(@String,@n,1) = SUBSTRING(@String, @StringLength,1)
SET @Palindrome = 1
ELSE
RETURN 0
Biorąc pod uwagę, że teraz używamy tylko @Palindromedo „wciąż jest to palindrom”, naprawdę nie ma sensu go mieć. Możemy pozbyć się zmiennej i przełączyć naszą logikę na zwarcie w przypadku awarii ( RETURN 0) i RETURN 1(reakcja pozytywna) tylko wtedy, gdy przejdzie ona przez całą pętlę. Zauważysz, że to faktycznie nieco upraszcza naszą logikę.
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(...))Biała przestrzeń?