1

我想要这个Java代码的简单正确的等价物:

Integer.parseInt(frameTagAsString, 16);

whereframeTagAsString是一个长度为 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 当然,我可以将值转换回十六进制字符串,然后与原始字符串进行比较 - 但我的问题是是否没有我错过的内置例程。

4

3 回答 3

3

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

十六进制整数表示可以可选地以 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);
    }

Even though these strings are invalid for an application that expects input to strictly be a string representing a hexadecimal number and nothing else, and some people may consider "x23" a valid hex string, this code gives the following output:

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

Since Java's Integer class and NSScanner have such different purposes, the rules they apply to validate strings are much different, and I think that's the root of your problem. If you do wish to use NSScanner, then you will have to apply validation rules that make sense for your application that would interfere with NSScanner's general operation.

于 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。

于 2013-03-30T02:30:41.900 回答