Vì có một số lượng lớn các giải pháp tôi sẽ thực hiện với phần "phê bình" trong câu hỏi của bạn. Một vài lưu ý: Tôi đã sửa một số lỗi chính tả và ghi chú nơi tôi đã làm. Nếu tôi sai về việc họ là một lỗi đánh máy đề cập đến nó trong các bình luận và tôi sẽ giải thích những gì đang xảy ra. Tôi sẽ chỉ ra một số điều mà bạn có thể đã biết, vì vậy xin đừng xúc phạm nếu tôi đã làm. Một số ý kiến có vẻ kén chọn nhưng tôi không biết bạn đang ở đâu trong hành trình của mình nên phải cho rằng bạn chỉ mới bắt đầu.
CREATE function Palindrome (
@String Char
, @StringLength Int
, @n Int
, @Palindrome BIN
, @StringLeftLength Int
LUÔN LUÔN bao gồm độ dài với một char
hoặc varchar
định nghĩa. Aaron Bertrand nói về chiều sâu ở đây . Anh ấy đang nói về varchar
nhưng điều tương tự cũng xảy ra char
. Tôi sẽ sử dụng một varchar(255)
cái này nếu bạn chỉ muốn các chuỗi tương đối ngắn hoặc có thể là một chuỗi varchar(8000)
lớn hơn hoặc thậm chí varchar(max)
. Varchar
dành cho các chuỗi có độ dài thay đổi chỉ dành cho các chuỗi char
cố định. Vì bạn không chắc chắn về độ dài của chuỗi được sử dụng varchar
. Ngoài ra binary
không phải vậy bin
.
Tiếp theo, bạn không cần đặt tất cả các biến đó làm tham số. Khai báo chúng trong mã của bạn. Chỉ đặt một cái gì đó trong danh sách tham số nếu bạn dự định chuyển nó vào hoặc ra. (Bạn sẽ thấy cái này trông như thế nào ở cuối.) Ngoài ra, bạn có @StringLeftLpm nhưng không bao giờ sử dụng nó. Vì vậy, tôi sẽ không tuyên bố nó.
Điều tiếp theo tôi sẽ làm là định dạng lại một chút để làm cho một vài điều rõ ràng.
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
Nếu bạn nhìn vào cách tôi thực hiện việc thụt lề, bạn sẽ nhận thấy rằng tôi có điều này:
WHILE @StringLength - @n >1
IF Left(@String,@n)=Right(@String, @StringLength)
SET @n = @n + 1
Đó là bởi vì các lệnh như WHILE
và IF
chỉ ảnh hưởng đến dòng mã đầu tiên sau chúng. Bạn phải sử dụng một BEGIN .. END
khối nếu bạn muốn nhiều lệnh. Vì vậy, sửa chữa mà chúng tôi nhận được:
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
Bạn sẽ nhận thấy rằng tôi chỉ thêm một BEGIN .. END
khối trong IF
. Đó là bởi vì mặc dù IF
câu lệnh dài nhiều dòng (và thậm chí chứa nhiều lệnh), nó vẫn chỉ là một câu lệnh (bao gồm mọi thứ được thực hiện trong IF
và các ELSE
phần của câu lệnh).
Tiếp theo bạn sẽ gặp lỗi sau cả hai RETURNs
. Bạn có thể trả về một biến HOẶC một nghĩa đen. Bạn không thể đặt biến và trả lại cùng một lúc.
SET @Palindrome = 1
END
ELSE
SET @Palindrome = 0
RETURN @Palindrome
Bây giờ chúng tôi đi vào logic. Trước tiên, hãy để tôi chỉ ra rằng LEFT
và các RIGHT
chức năng bạn đang sử dụng là tuyệt vời, nhưng chúng sẽ cung cấp cho bạn số lượng ký tự bạn chuyển từ hướng được yêu cầu. Vì vậy, hãy nói rằng bạn đã vượt qua trong từ "kiểm tra". Trên đường chuyền đầu tiên, bạn sẽ nhận được điều này (loại bỏ các biến):
LEFT('test',1) = RIGHT('test',4)
t = test
LEFT('test',2) = RIGHT('test',3)
te = est
Rõ ràng đó không phải là những gì bạn mong đợi. Bạn thực sự sẽ muốn sử dụng substring
thay thế. Chuỗi con cho phép bạn vượt qua không chỉ điểm bắt đầu mà cả chiều dài. Vì vậy, bạn sẽ nhận được:
SUBSTRING('test',1,1) = SUBSTRING('test',4,1)
t = t
SUBSTRING('test',2,1) = SUBSTRING('test',3,1)
e = s
Tiếp theo, bạn sẽ tăng các biến bạn sử dụng trong vòng lặp của mình chỉ trong một điều kiện của câu lệnh IF. Kéo hoàn toàn biến tăng ra khỏi cấu trúc đó. Điều đó sẽ yêu cầu một BEGIN .. END
khối bổ sung , nhưng tôi phải loại bỏ khối kia.
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
Bạn cần thay đổi WHILE
điều kiện của bạn để cho phép thử nghiệm cuối cùng.
WHILE @StringLength > @n
Và cuối cùng nhưng không kém phần quan trọng, hiện tại chúng ta không kiểm tra ký tự cuối cùng nếu có số lượng ký tự lẻ. Ví dụ với 'ana' n
không được thử nghiệm. Điều đó tốt nhưng đối với tôi, chúng ta cần tính đến một từ đơn (nếu bạn muốn nó được tính là tích cực). Vì vậy, chúng ta có thể làm điều đó bằng cách đặt giá trị lên phía trước.
Và bây giờ cuối cùng chúng ta cũng có:
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
Một bình luận cuối cùng. Tôi là một fan hâm mộ lớn của định dạng nói chung. Nó thực sự có thể giúp bạn xem cách mã của bạn hoạt động và giúp chỉ ra những sai lầm có thể xảy ra.
Chỉnh sửa
Như Sphinxxx đã đề cập, chúng tôi vẫn có một lỗ hổng trong logic của chúng tôi. Khi chúng tôi nhấn ELSE
và đặt @Palindrome
thành 0, không có điểm nào để tiếp tục. Trong thực tế tại thời điểm đó chúng ta có thể chỉ RETURN
.
IF SUBSTRING(@String,@n,1) = SUBSTRING(@String, @StringLength,1)
SET @Palindrome = 1
ELSE
RETURN 0
Cho rằng hiện tại chúng tôi chỉ đang sử dụng @Palindrome
cho "vẫn có thể đây là một bảng màu" thực sự không có lý do gì để có nó. Chúng ta có thể loại bỏ biến và chuyển logic của chúng ta thành ngắn mạch khi thất bại ( RETURN 0
và) và RETURN 1
(một phản ứng tích cực) chỉ khi nó thực hiện được tất cả các cách trong vòng lặp. Bạn sẽ nhận thấy điều này thực sự đơn giản hóa phần nào logic của chúng tôi.
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(...))
khoảng trắng?