Oldukça fazla sayıda çözüm bulunduğundan, sorunuzun “eleştirel” kısmına gideceğim. Birkaç not: Bazı yazım hataları düzelttim ve yaptığım yeri not aldım. Yazım hatası yapma konusunda yanılıyorsam yorumlarda belirtin ve neler olduğunu açıklayacağım. Bildiğiniz birkaç şeyi işaret edeceğim, öyleyse lütfen yapmayın. Bazı yorumlar seçici görünebilir ama yolculuğunuzda nerede olduğunuzu bilmiyorum bu yüzden yeni başladığınızı varsaymalıyım.
CREATE function Palindrome (
@String Char
, @StringLength Int
, @n Int
, @Palindrome BIN
, @StringLeftLength Int
HER ZAMAN uzunluğu char
veya varchar
tanımını içerir. Aaron Bertrand burada derinlemesine konuşur . O hakkında konuşuyor varchar
ama aynı şey için geçerli char
. Ben kullanmak istiyorum varchar(255)
sadece nispeten kısa dizeleri veya belki istiyorsanız bu için varchar(8000)
daha da büyük olanları veya varchar(max)
. Varchar
Değişken uzunluklu dizgiler char
sadece sabit olanlar içindir. Kullanımda geçirilen ipin uzunluğundan emin olamadığınızdan varchar
. Ayrıca binary
değil bin
.
Daha sonra tüm bu değişkenleri parametre olarak koymanız gerekmez. Onları kodunuzda bildirin. Parametre listesine yalnızca bir şeyi içeri veya dışarı aktarmayı planlıyorsanız koyun. (Bunun sonunda nasıl göründüğünü göreceksiniz.) Ayrıca @StringLeftLength var ama asla kullanmayın. Bu yüzden bunu ilan etmeyeceğim.
Yapacağım bir sonraki şey, birkaç şeyi açıklığa kavuşturmak için biraz yeniden biçimlendirmek.
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
Girintiyi yaptığım şekle bakarsanız şunu hissedeceksiniz:
WHILE @StringLength - @n >1
IF Left(@String,@n)=Right(@String, @StringLength)
SET @n = @n + 1
Bunun nedeni, komutların yalnızca bunlardan sonraki ilk kod satırını sevmesi WHILE
ve IF
etkilemesidir. BEGIN .. END
Birden fazla komut istiyorsanız, bir blok kullanmanız gerekir . Yani biz bunu düzeltmek:
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
İçinde sadece bir BEGIN .. END
blok eklediğimi fark edeceksiniz IF
. Bunun nedeni, IF
ifadenin çok satırlı olmasına rağmen (ve hatta birden çok komut içermesine rağmen), yine de tek bir ifadedir (ifadenin içinde IF
ve içinde yapılan her şeyi kapsayan ELSE
).
Sonra ikisinden de sonra bir hata ile karşılaşacaksınız RETURNs
. Bir değişkeni VEYA değişmezi döndürebilirsiniz. Değişkeni ayarlayıp aynı anda döndüremezsiniz.
SET @Palindrome = 1
END
ELSE
SET @Palindrome = 0
RETURN @Palindrome
Şimdi mantık içindeyiz. Öncelikle, kullandığınız LEFT
ve RIGHT
işlevlerinin harika olduğunu belirtmeme izin verin , ancak istenen yönden geçirdiğiniz karakter sayısını size verecekler. Diyelim ki "test" kelimesini geçtiniz. İlk geçişte bunu alacaksınız (değişkenleri kaldırarak):
LEFT('test',1) = RIGHT('test',4)
t = test
LEFT('test',2) = RIGHT('test',3)
te = est
Açıkçası beklediğiniz gibi değil. Bunun substring
yerine gerçekten kullanmak istersiniz . Altlık, yalnızca başlangıç noktasını değil, uzunluğu da geçmenizi sağlar. Böylece alırsınız:
SUBSTRING('test',1,1) = SUBSTRING('test',4,1)
t = t
SUBSTRING('test',2,1) = SUBSTRING('test',3,1)
e = s
Daha sonra, döngünüzde kullandığınız değişkenleri yalnızca IF ifadesinin bir koşulunda artıracaksınız. Değişkeni bu yapıdan tamamen dışarı çekerek çıkarın. Bu ek bir BEGIN .. END
blok gerektirecek , ama diğerini de kaldırıyorum.
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
Son teste izin vermek için durumunuzu değiştirmeniz gerekir .
WHILE @StringLength > @n
Ve sonuncusu ama en önemlisi, şu anki haliyle, tek sayıda karakter varsa son karakteri test etmiyoruz. Mesela 'ana' ile n
test edilmedi. Sorun değil, ancak tek harfli bir kelimeyi hesaba katmamız gerekiyor (eğer bunun pozitif olarak sayılmasını istiyorsanız). Böylece değeri ön ayarlayarak yapabiliriz.
Ve şimdi nihayet biz var:
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
Son bir yorum. Genel olarak formatın büyük bir hayranıyım. Kodunuzun nasıl çalıştığını görmenize ve olası hataları göstermenize yardımcı olabilir.
Düzenle
Sphinxxx'in dediği gibi, mantığımızda hala bir kusur var. Bir kere vurup 0'a ELSE
ayarladığımızda @Palindrome
devam etmenin bir anlamı yok. Aslında tam da bu noktada yapabiliriz RETURN
.
IF SUBSTRING(@String,@n,1) = SUBSTRING(@String, @StringLength,1)
SET @Palindrome = 1
ELSE
RETURN 0
Şimdi sadece @Palindrome
"hala bu bir palindrom olabilir" için kullandığımız göz önüne alındığında, buna sahip olmanın hiçbir anlamı yoktur. Değişkenden kurtulup mantığımızı başarısızlık (the ) ve (olumlu bir cevap) durumunda kısa devreye geçirebiliriz, ancak bunu tüm döngü boyunca gerçekleştirirse. Bunun aslında mantığımızı bir şekilde basitleştirdiğini fark edeceksiniz.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(...))
Beyaz boşluk?