かなりの数の解決策があるので、あなたの質問の「批評」の部分を取り上げます。いくつかのメモ:いくつかのタイプミスを修正し、どこに行ったかを書き留めました。それらがタイプミスであることが間違っている場合は、コメントでそれを言及し、何が起こっているのかを説明します。私はあなたがすでに知っているかもしれないいくつかの事柄を指摘するつもりですので、もし私がしたとしても怒らないでください。いくつかのコメントはうるさいように思えるかもしれませんが、私はあなたがあなたの旅のどこにいるか分からないので、あなたはちょうど始めていると仮定しなければなりません。
CREATE function Palindrome (
@String Char
, @StringLength Int
, @n Int
, @Palindrome BIN
, @StringLeftLength Int
常に Aと長さが含まれる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ステートメントの1つの条件でのみ、ループで使用する変数をインクリメントします。その構造から変数の増分を完全に引き出します。それには追加の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
ではテストされません。それは問題ありませんが、1文字の単語を説明する必要があります(肯定的なものとしてカウントしたい場合)。そのため、値を事前に設定することでそれを行うことができます。
そして今、私たちは最終的に持っています:
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が述べたように、私たちのロジックにはまだ欠陥があります。ヒットして0にELSE
設定@Palindrome
すると、続行する意味がなくなります。実際には、その時点で私たちはちょうどできましたRETURN
。
IF SUBSTRING(@String,@n,1) = SUBSTRING(@String, @StringLength,1)
SET @Palindrome = 1
ELSE
RETURN 0
現在@Palindrome
、「これは回文である可能性がある」ためだけに使用していることを考えると、実際にそれを使用する意味はありません。変数を取り除いて、失敗時()および(正の応答)でループを完全に通過した場合のみ、ロジックを短絡に切り替えることができます。これにより、ロジックが多少簡略化されていることに気付くでしょう。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(...))
空白?