Оскільки існує досить багато рішень, я збираюся піти з частиною «критики» вашого питання. Пару зауважень: я виправив кілька помилок друку і зазначив, куди потрапив. Якщо я помиляюся про те, що вони були помилковими, згадайте про це в коментарях, і я поясню, що відбувається. Я хочу зазначити кілька речей, які ви, можливо, вже знаєте, тому, будь ласка, не ображайтесь, якщо я це зробив. Деякі коментарі можуть здатися прискіпливими, але я не знаю, куди ти їдеш, тому треба припустити, що ти тільки починаєш.
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
І останнє, але не в останню чергу, те, як він стоїть зараз, ми не перевіряємо останнього символу, якщо є непарна кількість символів. Наприклад, "ana" 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
для "все ще можливо, це паліндром", насправді немає сенсу в ньому. Ми можемо позбутися змінної і переключити свою логіку на коротке замикання на відмову (the 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(...))
пробіл?