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 charo varchardefinizione. Aaron Bertrand ne parla in modo approfondito qui . Sta parlando varcharma 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 WHILEe IFinfluenzano solo la prima riga di codice dopo di essi. Devi usare un BEGIN .. ENDblocco 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 .. ENDblocco in IF. Questo perché anche se l' IFistruzione è lunga più righe (e contiene anche più comandi) è comunque una singola istruzione (che copre tutto ciò che viene eseguito nelle parti IFe ELSEdell'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 LEFTe RIGHTche 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 substringinvece. 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 .. ENDblocco 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 WHILEcondizioni 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" nnon è 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 ELSEe impostato @Palindromesu 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 @Palindromeper "è 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?