Поскольку существует немало решений, я собираюсь остановиться на «критической» части вашего вопроса. Несколько замечаний: я исправил некоторые опечатки и отметил, где я сделал. Если я ошибаюсь из-за того, что они опечатки, упомяните об этом в комментариях, и я объясню, что происходит. Я собираюсь указать на несколько вещей, которые вы, возможно, уже знаете, поэтому, пожалуйста, не обижайтесь, если я это сделал. Некоторые комментарии могут показаться придирчивыми, но я не знаю, где вы находитесь в вашем путешествии, поэтому я должен предположить, что вы только начинаете.
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(...))
пробельные?