1

このJavaコードに相当する簡単で正しいものを用意したいと思います:

Integer.parseInt(frameTagAsString, 16);

frameTagAsString長さ 2 の文字列はどこにありますか。

16 進文字列を int 値に解析する方法は知っていますが、

    unsigned int uint;
    NSScanner* pScanner = [NSScanner scannerWithString: frameTagAsString];
    [pScanner scanHexInt: &uint];
    frameType = uint;

問題は、無効な文字列を解析して int 値にすることです。

これらの無効なケースを明示的にキャッチする必要があります。だから私はこれを試しました:

 @try {
    // the String to int conversion happens here
    //frameType = Integer.parseInt(frameTagAsString, 16);
    unsigned int uint;
    NSScanner* pScanner = [NSScanner scannerWithString: frameTagAsString];
    [pScanner scanHexInt: &uint];
    frameType = uint;

} @catch (NSException* nfe) {
    frameType = -1;
}

また、目的の C コードは文字列を解析するだけなので、無効なケースを正しくキャッチできません。

有効な 16 進文字列もチェックする独自の変換ルーチンを Objective-C で作成する以外に方法はありませんか?

psもちろん、値を16進文字列に変換して元の文字列と比較することもできますが、見逃したルーチンが既に組み込まれていないかどうかが問題です。

4

3 に答える 3

3

NSScannerNO検証規則に従って、有効な文字列が見つからない場合に戻ります。

オプションで、16 進整数表現の前に 0x または 0X を付けることができます。

これを示すサンプル コードを次に示します。

    NSString *valid1 = @"ae";
    NSString *valid2 = @"0xae";
    NSString *valid3 = @"0Xae";
    NSString *invalid1 = @"ze";
    NSString *invalid2 = @"hello";

    void (^scanBlock)(NSString *) = ^(NSString *toScan) {
        NSScanner *scanner = [NSScanner scannerWithString:toScan];
        UInt32 parsed = 0;
        BOOL success = [scanner scanHexInt:&parsed];
        NSLog(
            @"Scanner %@ able to scan the string %@. parsed's value is %x",
            success ? @"was" : @"wasn't",
            toScan,
            parsed);
    };

    for (NSString *valid in @[ valid1, valid2, valid3]) {
        scanBlock(valid);
    }

    for (NSString *invalid in @[invalid1, invalid2]) {
        scanBlock(invalid);
    }

上記のコードの出力は次のとおりです。

Scanner was able to scan the string ae. parsed's value is ae
Scanner was able to scan the string 0xae. parsed's value is ae
Scanner was able to scan the string 0Xae. parsed's value is ae
Scanner wasn't able to scan the string ze. parsed's value is 0
Scanner wasn't able to scan the string hello. parsed's value is 0

ただし、その柔軟な性質によりNSScanner、直接のスキャン位置以外の検証ルールは適用されません。また、他の人が有効な 16 進文字列と見なす可能性のある一部の文字列を無効と認識します。例えば:

    NSString *greyArea1 = @"x23";
    NSString *greyArea2 = @"artichoke";
    NSString *greyArea3 = @"1z";
    NSString *greyArea4 = @"     a3";

    for (NSString *grey in @[greyArea1, greyArea2, greyArea3, greyArea4]) {
        scanBlock(grey);
    }

これらの文字列は、入力が厳密に 16 進数を表す文字列であることを期待するアプリケーションでは無効であり、「x23」を有効な 16 進文字列と見なす人もいるかもしれませんが、このコードは次の出力を提供します。

Scanner wasn't able to scan the string x23. parsed's value is 0
Scanner was able to scan the string artichoke. parsed's value is a
Scanner was able to scan the string 1z. parsed's value is 1
Scanner was able to scan the string      a3. parsed's value is a3

Java のIntegerクラス とNSScannerはそのような異なる目的を持っているため、文字列を検証するために適用されるルールは大きく異なります。それが問題の根本だと思います。を使用したい場合はNSScanner、アプリケーションにとって意味のある検証規則を適用する必要があります。これは、NSScannerの一般的な操作に干渉します。

于 2013-03-30T03:39:31.230 に答える
1

どうですか

uint = [frameTagAsString intValue];

ドキュメントによると、無効な文字列入力では 0 を返します。

あるいは、0 は依然として有効な数値であり、正規表現を使用できることを示すものではないためです。

NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^(\\d+)$"
                                                                       options:NSRegularExpressionCaseInsensitive
                                                                         error:NULL];

NSTextCheckingResult *match = [regex firstMatchInString:frameTagAsString
                                            options:0
                                              range:NSMakeRange(0, [string length])];
if (match) {
    uint = [frameTagAsString substringWithRange:[match range]];
} else {
    // error
}
于 2013-03-30T02:24:06.150 に答える
1

このようなものがうまくいくはずです。

int value;
NSScanner* pScanner = [NSScanner scannerWithString:@"123abc456"];
NSCharacterSet *charSet = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
[pScanner setCharactersToBeSkipped:charSet];
while(![pScanner isAtEnd]) {
    if([pScanner scanInt: &value])
        NSLog(@"%d", value);
}

出力:

2013-03-29 20:29:12.648 scanner.m.uQzuCBsY[3753:707] 123
2013-03-29 20:29:12.650 scanner.m.uQzuCBsY[3753:707] 456

scanInt:有効な int が見つかったかどうかを示す bool を返します。

于 2013-03-30T02:30:41.900 に答える