0

forループがあります。

for (i=0; i <= stringLength; i++) {

unichar currentCharacter = [string characterAtIndex:i];

...}

ドキュメントから、 characterAtIndex: は通常「unichar」型の値を返すことを理解していますが、インデックスが範囲外の場合は NSRangeException が返されます。

注意して、[string characterAtIndex:i] が NSRangeException を返しているかどうかを確認してから、戻り値を currentCharacter に割り当てます。

私が最初に試したのはこれでした:

if ([string characterAtIndex:i] != NSRangeException)

...しかし、私の理解では、メソッドは通常intを返し、それを文字列であるNSRangeExceptionと比較しているため、機能しません。

[string characterAtIndex:i] isKindOfClass:...] について考えましたが、[string characterAtIndex:i] は NSObject ではないため、機能しません。では、例外をテストするにはどうすればよいでしょうか。

例外をテストする必要がありますか? 返される値がプリミティブである場合と NSObject である場合がある場合、その型をテストするにはどうすればよいですか?

4

2 に答える 2

1

こんにちはオリバー、私はこの質問に出くわしたばかりで、答えようと思っていました.

まず、インデックスが厳密にstringLength未満でstringLength == [string length]あることを確認する必要があると仮定します。つまり、以下ではありません。

for (i=0; i < stringLength; i++) {

  unichar currentCharacter = [string characterAtIndex:i];

...}

たとえば、5 文字の文字列には 5 つの有効なインデックスがあります。0、1、2、3、4。

その修正により、例外が発生するのを防ぐ必要がありますが、例外についてさらに説明します (インデックスの off-by-one エラーに気付く前に書いたものです)。

例外は通常の戻り値とは異なり、関数が呼び出し元にエラー状態を通知できる特別な緊急チャネルのようなものであり、エラー状態を通常の戻り値に詰め込む必要はありません。

用語は、例外は「発生」または「スロー」されるほど「返される」わけではないということです (言語によって異なります)。次に、例外が「キャッチ」または「レスキュー」されます (言語によって異なります)。

例外は例外的な状況でのみ使用する必要があり、(入力をサニタイズすることによって) 例外を回避する何らかの方法がある場合は、最初にそれを行う必要があります。可能であれば例外を避けるもう 1 つの理由は、一部の言語では、例外をキャッチするプロセスが非常に効率的でなく、メモリ割り当てが少し不安定になる可能性があることです。

ただし、例外的な状況では、戻り値の範囲でエラー状態を表現する方法を工夫する必要なく、呼び出し元の関数にエラーを通知する便利な方法です。

それでは、実用性に移ります。あなたのケースで例外をキャッチするための構文は次のようになります。

@try {
  for (i=0; i <= stringLength; i++) {
    unichar currentCharacter = [string characterAtIndex:i];
  }
} 
@catch (NSException *exception) {
  NSLog(@"uh oh..");
  // handle the exception here
}

これにより、NSRangeException だけでなく、スローされたすべての例外がキャッチされます。多くの言語では、 のような構文を使用してより選択的にすることができますが@catch (NSRangeException *exception)、残念ながら、Objective-C ではそうではありません。これは、NSRangeException が NSException のサブクラスとして定義されておらず、代わりに NSException の -name 値に現れる NSString 定数であるためです。Objective-C でより選択的にするには、次のようにする必要があります。

@catch (NSException *exception) {
  if ([[exception name] isEqualToString:NSRangeException]) {
    NSLog("got an NSRangeException");
    // handle the exception here
  } else {
    NSLog("got an exception we can't handle so pass it down the chain");
    @throw exception;
  }
}

ご覧のとおり、例外をキャッチするのは非常に厄介な場合があるため、常に例外を回避することをお勧めします。このコードが NSRangeException をトリガーする場合、非常に例外的な (そしておそらく制御できない) 何かが発生しているに違いありません。

for (i=0; i < [string length]; i++) {

  unichar currentCharacter = [string characterAtIndex:i];

...}
于 2013-12-11T02:29:35.493 に答える
0

また、基本的に変更可能な文字列でこれを行うべきではないことにも注意してください。不変のコピーを作成します。不変の文字列で本当に試してみたい場合は、最後から逆方向に反復する必要があります。for ループの反復基準で長さが変更されていないと主張することも合理的です。

于 2013-12-11T05:24:48.153 に答える