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ą char
lub varchar
. Aaron Bertrand mówi tutaj dogłębnie . Mówi, varchar
ale 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)
. Varchar
jest dla ciągów o zmiennej długości char
jest tylko dla stałych. Ponieważ nie jesteś pewien długości przekazywanego ciągu w użyciu varchar
. Także to binary
nie 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 WHILE
i IF
wpływają tylko na pierwszy wiersz kodu po nich. Musisz użyć BEGIN .. END
bloku, 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 .. END
blok w IF
. To dlatego, mimo że IF
oświadczenie jest wiele linii długo (a nawet zawiera wiele poleceń) jest jeszcze jedno sprawozdanie (obejmujące wszystko wykonywane w IF
a ELSE
częś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 LEFT
i 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ć substring
zamiast 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 .. END
bloku, 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 WHILE
stan, 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” n
nie 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 ELSE
i ustawieniu @Palindrome
na 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 @Palindrome
do „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ń?