1

私は Array のサブクラスを作成し、それに対するいくつかのメッセージを書きましたが、これまでのところうまくいきました。ただし、最後のメッセージで問題が発生しました。コードの本文は次のとおりです。

startString: charToTest
"Returns a list of all the words that start with a given character"
|  toReturn i j numWords |
i:= 1.
j:= 1.
numWords := 0.
[i <= self size.] whileTrue: [
    (((self at: i) at: 1) = charToTest)
        ifTrue: [numWords := numWords + 1].
    i:= i+1.
].
toReturn := MyArray new: numWords.
i := 1. 
[i <= numWords.] whileTrue: [
    (((self at: i) at: 1) = charToTest)
        ifTrue: [toReturn at: j put: (self at: i). j := j+1].
    i := i + 1.
].
^toReturn

したがって、本質的に、メソッドはそれ自体を調べて、その文字で始まる単語の数のサイズの新しい配列を作成します。その後、再び反復し、これらの単語を新しい配列に入れ、それを返します。私のワークスペースは次のようになります。

|freshArray testArray|
freshArray := MyArray new: 5.
freshArray
    at: 1 put: 'some';
    at: 2 put: 'things';
    at: 3 put: 'are';
    at: 4 put: 'simple';
    at: 5 put: 'things'.
testArray := freshArray startString: $s

ワークスペースでこのコードを選択して印刷すると、この方法はほぼ正しいです。しかし、そうではありません。何らかの理由で、「toReturn」の 2 番目のスロットが埋まっていません。出力は次のようになります。

 a MyArray('some' nil)

なぜこうなった?if ステートメントの後の 2 番目の反復ループで、ステートメントを正しく分離していますか? 私は自分が間違ったことをしていたことについて本当に混乱しています。どんな助けでも大歓迎です!

4

2 に答える 2

1

最初の反復では、指定された文字で始まる単語の数をカウントします (文字列が空ではないことを前提としていますが、後でそのチェックを含めることができます)。ここまでは順調ですね。ただし、そのカウント (numWords) を使用して配列を再度反復処理する 2 回目は、最初の配列の最初の 'numWords' スロットにある単語のみが考慮されることを意味します。

(while を do: aBlock に置き換えることを検討することもできます。これは、はるかに煩雑でなく、より Smalltalk 的です)。

于 2012-04-24T19:54:32.010 に答える
1

よりコンパクトな形式を使用する傾向があります。

testArray := freshArray select: [:each | charToTest = each first ]

入力に空の文字列がある場合、これは失敗することに注意してください

于 2012-05-02T09:31:09.577 に答える