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
我最近继承了一些 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 socharacterAtIndex:
returns aunichar
(a 16-bit type) hence the type offlag
. 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