Objective-c: 为什么我继承的这段代码用的是strtol方法?

Objective-c: Why is strtol method used in this code I inherited?

我最近继承了一些 Objective-C 代码,我真的很困惑它到底在做什么?

1) 我不明白为什么 char byte_chars[3] 会先填充一个“0”,然后再填充一个 0?

2) 我不明白为什么他们对 wholeByte 使用 unsigned char,但要放入 long?

3) 部分我对 strtol 方法在这里的作用有点困惑,它需要 3 byte_chars 个字节(十六进制),然后将它们转换为 long?

- (NSString *)starFromFlags:(NSString *)flags {
    unsigned char wholeByte; 
    char byte_chars[3];
    NSString *star = @"NO";

    byte_chars[0] = '0'; 
    byte_chars[1] = [flags characterAtIndex:1]; 
    byte_chars[2] = 0; 
    wholeByte = strtol(byte_chars, NULL, 16); 

    if (wholeByte & 0x01) star = @"YES";

    return star;
}

致 1:

末尾的0是末尾的'\0'(均为零值),表示"string ends here"。你必须把它放在最后才能结束字符串。

开头的“0”(字母 0)表示 strtol() 的八进制值(不是十六进制,应该是“0x”)。但正如 CRD 正确提到的那样(见评论),它在这里被传递给 strtol() 的第三个参数覆盖。所以到这里为止,您有一个双字母字符串,第一个字符为 0,第二个字符为标志的十六进制表示形式。

原因可能是,flags 包含从“0”到 'f'₁₆/'F'₁₆(0 到 15₁₀)的数字。

致 2:

由于转换产生的值在 [0…15] 范围内,long 值将具有此值之一。您可以将它存储在一个字节中,不需要整整一个字节。但是,strtol() 总是 returns 长。

致 3:

是的,它是将包含数字的字符串转换为数字。 IE。 字符串 "06" 将被转换为数字 6.

Amin Negm-Awad 已经解释了代码的作用(对八进制有点混淆),但关于回答您的问题:

Why is strtol method used in this code I inherited?

我们只能猜测。

似乎字符串中的第二个字符是用于(最多)4 个标志位的十六进制数字,该方法正在测试是否设置了这些中的最低有效位。一个更简单的方法可能是:

- (NSString *)starFromFlags:(NSString *)flags
{
   unichar flag = [flags characterAtIndex:1];

   if (flag > 127 || !isxdigit(flag))  // check flag is in ASCII range and hex digit
      return @"INVALID";
   else
      return digittoint(flag) & 0x1 ? @"YES" : @"NO"; // check if flag is odd hex
}

isxdigit()digittoint() 是 C 库函数(就像 strtol()),在终端中使用 man isxdigit 获取文档(除非您使用的是旧版本Xcode 中有这些文档的,Apple 无助地删除了最新版本中的文档)。第一个检查字符是否为十六进制数字,第二个 returns 是等价的整数。 > 127 检查是针对字符串中非 "ASCII" 字符的最低限度保护。

Note: An NSString (presents itself as) as sequence of UTF-16 code units so characterAtIndex: returns a unichar (a 16-bit type) hence the type of flag. However this code doesn't handle any unicode string correctly. If your strings are "ASCII" it will work.

上面的函数实际上比原来做了更多的错误检查,如果你愿意减少错误检查,你可以使用:

- (NSString *)starFromFlags:(NSString *)flags
{
   return digittoint([flags characterAtIndex:1]) & 0x1 ? @"YES" : @"NO";
}

这将 return @"YES" 当且仅当标志是十六进制数字并且其 LSB 已设置时,如果它不是十六进制数字或 LSB 未设置它 returns @"NO"。这是有效的,因为 digittoint() returns 0 如果它的参数不是十六进制数字。

那么当初的程序员为什么要用strtol()呢?也许他们不知道 digittoint().

HTH