Поскольку существует немало решений, я собираюсь остановиться на «критической» части вашего вопроса. Несколько замечаний: я исправил некоторые опечатки и отметил, где я сделал. Если я ошибаюсь из-за того, что они опечатки, упомяните об этом в комментариях, и я объясню, что происходит. Я собираюсь указать на несколько вещей, которые вы, возможно, уже знаете, поэтому, пожалуйста, не обижайтесь, если я это сделал. Некоторые комментарии могут показаться придирчивыми, но я не знаю, где вы находитесь в вашем путешествии, поэтому я должен предположить, что вы только начинаете.
CREATE function Palindrome (
@String Char
, @StringLength Int
, @n Int
, @Palindrome BIN
, @StringLeftLength Int
ВСЕГДА указывайте длину с определением charили varchar. Аарон Бертран подробно рассказывает здесь . Он говорит о, varcharно то же самое касается char. Я бы использовал varchar(255)для этого, если вы хотите только относительно короткие строки или, возможно, varchar(8000)для более крупных или даже varchar(max). Varcharдля строк переменной длины char- только для фиксированных. Поскольку вы не уверены в длине строки, передаваемой в использование varchar. И это binaryне так bin.
Далее вам не нужно помещать все эти переменные в качестве параметров. Объявите их в своем коде. Поместите что-либо в список параметров только в том случае, если вы планируете передавать его или нет. (Вы увидите, как это выглядит в конце.) Также у вас есть @StringLeftLength, но вы никогда его не используете. Так что я не собираюсь это объявлять.
Следующее, что я собираюсь сделать, это немного переформатировать, чтобы сделать несколько вещей очевидными.
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
Если вы посмотрите, как я сделал отступ, то заметите, что у меня есть это:
WHILE @StringLength - @n >1
IF Left(@String,@n)=Right(@String, @StringLength)
SET @n = @n + 1
Это потому, что команды любят WHILEи IFвлияют только на первую строку кода после них. Вы должны использовать BEGIN .. ENDблок, если вы хотите несколько команд. Так что исправим, что получим:
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
Вы заметите, что я только добавил BEGIN .. ENDблок в IF. Это связано с тем, что, хотя IFоператор состоит из нескольких строк (и даже содержит несколько команд), он по-прежнему является одним оператором (охватывающим все, что выполняется в операторе IFи его ELSEчастях).
Далее вы получите ошибку после обоих ваших RETURNs. Вы можете вернуть переменную ИЛИ литерал. Вы не можете установить переменную и вернуть ее одновременно.
SET @Palindrome = 1
END
ELSE
SET @Palindrome = 0
RETURN @Palindrome
Теперь мы в логике. Прежде всего позвольте мне отметить, что LEFTи RIGHTфункции , которые вы используете большие, но они собираются дать вам количество символов , которые проходят в от запрошенной направлении. Допустим, вы прошли слово «тест». На первом проходе вы получите это (удаление переменных):
LEFT('test',1) = RIGHT('test',4)
t = test
LEFT('test',2) = RIGHT('test',3)
te = est
Очевидно, это не то, что вы ожидали. Вы бы действительно хотели использовать substringвместо этого. Подстрока позволяет передавать не только начальную точку, но и длину. Таким образом, вы получите:
SUBSTRING('test',1,1) = SUBSTRING('test',4,1)
t = t
SUBSTRING('test',2,1) = SUBSTRING('test',3,1)
e = s
Затем вы увеличиваете переменные, которые используете в цикле, только в одном условии оператора IF. Вытяните переменную, постепенно увеличивающуюся из этой структуры. Это потребует дополнительного BEGIN .. ENDблока, но я могу удалить другой.
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
Вы должны изменить свое WHILEсостояние, чтобы учесть последний тест.
WHILE @StringLength > @n
И последнее по порядку, но не по значению: как сейчас, мы не проверяем последний символ, если есть нечетное количество символов. Например, с «аной» nне тестируется. Это нормально, но мне нужно учесть одно буквенное слово (если вы хотите, чтобы оно считалось положительным). Таким образом, мы можем сделать это, установив значение заранее.
И теперь мы наконец имеем:
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
Последний комментарий Я большой поклонник форматирования в целом. Это действительно может помочь вам увидеть, как работает ваш код и указать на возможные ошибки.
редактировать
Как упоминал Sphinxxx, у нас все еще есть недостаток в нашей логике. Как только мы нажмем ELSEи установим @Palindromeв 0, продолжать нет смысла. На самом деле в тот момент мы могли просто RETURN.
IF SUBSTRING(@String,@n,1) = SUBSTRING(@String, @StringLength,1)
SET @Palindrome = 1
ELSE
RETURN 0
Учитывая, что мы сейчас используем только @Palindromeдля «это все еще возможно, это палиндром», на самом деле нет смысла иметь его. Мы можем избавиться от переменной и переключить нашу логику на короткое замыкание при сбое ( RETURN 0) и RETURN 1(положительный ответ) только в том случае, если оно проходит весь цикл. Вы заметите, что это несколько упрощает нашу логику.
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(...))пробельные?