【问题标题】:Parse Objective-C printf Format Strings?解析 Objective-C printf 格式字符串?
【发布时间】:2013-01-07 18:13:48
【问题描述】:

我想获取使用+[NSString stringWithFormat:] 构建的NSString 中的成员范围。解析objective-c格式字符串的最佳方法是什么?因为%@,我不能只使用C 格式的字符串解析器。我还需要确保它支持格式排序:%1$d%2$@ 等。

例如,使用[NSString stringWithFormat:@"foo %2$@ bar %1$@", @"Heath", @"Borders"] 构建的字符串,理想情况下我会喜欢以下NSArray@[NSMakeRange(15, 5), NSMakeRange(4, 6)]。第一个数组对象对应格式字符串中的第一个数据元素,第二个数组对象对应第二个数据元素,以此类推

在这种情况下,API 类似于+ (NSString *) stringWithFormatRanges:(NSArray **)outFormatRanges withFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2); 它会返回一个NSString,就像+[NSString stringWithFormat:] 一样,但它也会返回一个NSArray,每个格式数据元素都有NSRanges。

-- 编辑--

鉴于这个问题已经存在 3 年了,我很乐意在这一点上使用纯 C 实现。

【问题讨论】:

  • 解析方式,您的具体要求是什么...请解释一下。
  • “成员范围”是什么意思?您是说要解析“%@”、“%1$d”和“%2$@”等子字符串吗?
  • 我认为您应该首先提取单个格式项,也许使用 RE,然后编写代码来检查它们并对其进行分类。
  • 尽管没有记录,C printf()%n specifier 在 Objective-C 中是否按预期工作?如果是这样,这就像在 stringWithFormat 周围编写一个包装器一样简单,该包装器在其他说明符之前和之后立即注入 %n,调用格式化程序,然后将字节计数后处理为您需要的任何形式。
  • @HeathBorders 好吧,C 标准对printf() 的描述使用一组不相交的字符作为转换说明符以及介于两者之间的字符(标志、字段宽度、精度、长度修饰符)。困扰我的是%@ 转换说明符可能不受普通printf() 支持,但%n 可能不受stringWithFormat 支持。

标签: objective-c c printf


【解决方案1】:

几年前我研究过这个问题。如果我理解您的问题,则没有简单的方法可以从 C 或 Cocoa 格式字符串的格式字符串中获取 AST。

我编写了 NSXMLElement+elementWithXMLFormat,它允许将 NSXMLElements 非转义插入到具有特殊 %%%@ 格式代码的格式字符串中,这需要扩展 Cocoa 的格式。我的技术可能对你有帮助:

https://github.com/rentzsch/nsxmlelement-elementwithxmlformat/blob/937b54b2a830a8fbbd72d6bc5e48bafd495ddcbd/NSXMLElement%2BelementWithXMLFormat.m#L41

我只提取格式代码并用 NUL 分隔,以传统方式运行它,然后重新组装。

【讨论】:

  • 谢谢!今晚我会看看这个。它看起来很有希望。
【解决方案2】:

我为我的工具 SwiftGen 用 Swift 编写了一个解析器(这样我就可以检测 Localizable.strings 中的那些占位符,并提取在使用这些字符串调用 stringWithFormat: 时应该给出哪些类型)

可以看到解析there on my GitHub的部分代码。

  • 当然,它是 Swift 而不是 Objective-C,但我想它很容易转换为 ObjC,只要你保持算法的逻辑。
  • 我的代码也没有返回范围作为这些函数的输出——只有类型——但是typesFromFormatString 函数中的代码肯定可以访问这些占位符的范围,并且除了检测到的之外还可以完全返回它们类型(这是一个简单的更改,我只是不需要这些范围,所以我没有将它们包含在返回类型中)

(一旦你有了%d%2$@ 等占位符的范围,就很容易推断出字符串参数的范围:第一个范围与.location 相同第一个占位符但替换值的长度,第二个范围将具有第二个占位符的.location + (firstValue.length-firstRange.length) 以考虑偏移量等)

HTH。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多