目标C中的Java代码的等价物:Integer.parseInt(frameTagAsString,16);

时间:2013-03-30 02:14:54

标签: java objective-c hex

我希望有一个简单正确的等效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;
}

由于目标C代码只解析任何字符串,因此无法正确捕获无效案例。

除了在objective-C中编写我自己的转换例程以检查有效的十六进制字符串之外,没有其他选择吗?

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

3 个答案:

答案 0 :(得分:3)

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一般操作的验证规则。

答案 1 :(得分:1)

怎么样?
uint = [frameTagAsString intValue];

根据documentation,它在无效的字符串输入上返回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
}

答案 2 :(得分: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:返回一个bool,说明它是否找到了有效的int。