等效的Java代码在objective C:整数.方法(frameTagAsString 16);



我想有一个简单正确的等效Java代码:

Integer.parseInt(frameTagAsString, 16);

其中frameTagAsString是长度为2的字符串。

虽然我知道如何将十六进制字符串解析为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;
}

由于objective C代码只是解析任何字符串,它将无法正确捕获无效的情况。

有没有其他的选择,而不是写我自己的转换例程在objective-C,也检查一个有效的十六进制字符串?

当然,我可以将值转换回十六进制字符串,然后与原始字符串进行比较-但我的问题是,如果没有一个已经构建的例程,我错过了。

如果NSScanner没有找到有效的字符串,则根据其验证规则返回NO:

十六进制整数表示可以选择在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的灵活性,它不会应用超出其当前扫描位置的验证规则。它还将一些其他人认为有效的十六进制字符串视为无效字符串。例如:

    NSString *greyArea1 = @"x23";
    NSString *greyArea2 = @"artichoke";
    NSString *greyArea3 = @"1z";
    NSString *greyArea4 = @"     a3";
    for (NSString *grey in @[greyArea1, greyArea2, greyArea3, greyArea4]) {
        scanBlock(grey);
    }

即使这些字符串对于期望输入严格为表示十六进制数的字符串的应用程序是无效的,并且有些人可能认为"x23"是一个有效的十六进制字符串,这段代码给出了以下输出:

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的一般操作。

像这样的东西应该可以为您工作。

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:返回一个bool值,表示是否找到一个有效的int值。

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
}

最新更新