Dato che ci sono un discreto numero di soluzioni, vado con la parte "critica" della tua domanda. Un paio di note: ho corretto alcuni errori di battitura e ho notato dove ho fatto. Se sbaglio sul fatto che sono un errore di battitura, menzionalo nei commenti e spiegherò cosa sta succedendo. Sottolineerò diverse cose che potresti già sapere, quindi per favore non offenderti se l'ho fatto. Alcuni commenti possono sembrare schizzinosi ma non so dove ti trovi nel tuo viaggio, quindi devi presumere che stai appena iniziando.
CREATE function Palindrome (
@String Char
, @StringLength Int
, @n Int
, @Palindrome BIN
, @StringLeftLength Int
Includere SEMPRE la lunghezza con a char
o varchar
definizione. Aaron Bertrand ne parla in modo approfondito qui . Sta parlando varchar
ma lo stesso vale per char
. Userei a varchar(255)
per questo se vuoi solo stringhe relativamente corte o forse una varchar(8000)
per quelle più grandi o anche varchar(max)
. Varchar
è per stringhe a lunghezza variabile char
è solo per quelle fisse. Dato che non sei sicuro della lunghezza della stringa che viene passata in uso varchar
. Inoltre non lo binary
è bin
.
Successivamente non è necessario inserire tutte queste variabili come parametri. Dichiarali nel tuo codice. Inserisci qualcosa nell'elenco dei parametri solo se prevedi di passarlo dentro o fuori. (Vedrai come appare alla fine.) Inoltre hai @StringLeftLength ma non lo usi mai. Quindi non lo dichiarerò.
La prossima cosa che farò è riformattare un po 'per rendere ovvie alcune cose.
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
Se guardi come ho fatto il rientro noterai che ho questo:
WHILE @StringLength - @n >1
IF Left(@String,@n)=Right(@String, @StringLength)
SET @n = @n + 1
Questo perché i comandi gradiscono WHILE
e IF
influenzano solo la prima riga di codice dopo di essi. Devi usare un BEGIN .. END
blocco se vuoi più comandi. Così riparando che otteniamo:
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
Noterai che ho aggiunto solo un BEGIN .. END
blocco in IF
. Questo perché anche se l' IF
istruzione è lunga più righe (e contiene anche più comandi) è comunque una singola istruzione (che copre tutto ciò che viene eseguito nelle parti IF
e ELSE
dell'istruzione).
Successivamente riceverai un errore dopo entrambi RETURNs
. È possibile restituire una variabile o un valore letterale. Non è possibile impostare la variabile e restituirla contemporaneamente.
SET @Palindrome = 1
END
ELSE
SET @Palindrome = 0
RETURN @Palindrome
Ora siamo nella logica. Prima di tutto, vorrei sottolineare che le funzioni LEFT
e RIGHT
che stai utilizzando sono fantastiche, ma ti daranno il numero di caratteri che passi dalla direzione richiesta. Supponiamo che tu abbia passato la parola "test". Al primo passaggio otterrai questo (rimuovendo le variabili):
LEFT('test',1) = RIGHT('test',4)
t = test
LEFT('test',2) = RIGHT('test',3)
te = est
Ovviamente non è quello che ti aspettavi. Si vorrebbe davvero usare substring
invece. Il sottostringa ti consente di passare non solo il punto iniziale ma la lunghezza. Quindi otterresti:
SUBSTRING('test',1,1) = SUBSTRING('test',4,1)
t = t
SUBSTRING('test',2,1) = SUBSTRING('test',3,1)
e = s
Successivamente si stanno incrementando le variabili utilizzate nel proprio ciclo solo in una condizione dell'istruzione IF. Estrai la variabile incrementando completamente da quella struttura. Ciò richiederà un BEGIN .. END
blocco aggiuntivo , ma riesco a rimuovere l'altro.
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
È necessario modificare le WHILE
condizioni per consentire l'ultimo test.
WHILE @StringLength > @n
E, ultimo ma non meno importante, il modo in cui si trova ora non testiamo l'ultimo personaggio se c'è un numero dispari di personaggi. Ad esempio con "ana" n
non è stato testato. Va bene, ma a me serve tenere conto di una parola di una sola lettera (se vuoi che sia considerata positiva). Quindi possiamo farlo impostando il valore in anticipo.
E ora finalmente abbiamo:
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
Un ultimo commento Sono un grande fan della formattazione in generale. Può davvero aiutarti a vedere come funziona il tuo codice e ad evidenziare possibili errori.
modificare
Come menzionato da Sphinxxx, abbiamo ancora un difetto nella nostra logica. Una volta premuto il tasto ELSE
e impostato @Palindrome
su 0, non ha senso continuare. In effetti a quel punto potremmo solo RETURN
.
IF SUBSTRING(@String,@n,1) = SUBSTRING(@String, @StringLength,1)
SET @Palindrome = 1
ELSE
RETURN 0
Dato che ora stiamo usando solo @Palindrome
per "è ancora possibile che questo sia un palindromo" non ha davvero senso averlo. Possiamo liberarci della variabile e cambiare la nostra logica in corto circuito in caso di guasto (il RETURN 0
) e RETURN 1
(una risposta positiva) solo se riesce a superare il ciclo. Noterai che questo in realtà semplifica in qualche modo la nostra logica.
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(...))
spazio bianco?