【问题标题】:Equivalent of Java code in objective C: Integer.parseInt(frameTagAsString, 16);等效于目标 C 中的 Java 代码:Integer.parseInt(frameTagAsString, 16);
【发布时间】:2013-03-20 19:11:40
【问题描述】:

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

【问题讨论】:

    标签: java objective-c hex


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      这样的东西应该适合你。

      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。

      【讨论】:

      • thnaks - 但与 Java 相比复杂得多 :-)
      【解决方案3】:

      怎么样

      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
      }
      

      【讨论】:

      • 谢谢,但 0 又是一个有效数字,也可能是有效的十六进制值
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-10-26
      • 1970-01-01
      • 2014-02-03
      • 1970-01-01
      • 1970-01-01
      • 2011-12-18
      • 1970-01-01
      相关资源
      最近更新 更多