本文介绍了支持哪些 Swift 字符串格式说明符?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Swift 中,我可以使用格式说明符格式化字符串:

//这将返回0.120"字符串(格式:%.03f",0.12)

但官方文档没有提供任何关于支持的格式说明符或如何构建类似于 "%.03f" 的模板的信息或链接:https://developer.apple.com/documentation/swift/string/3126742-init

它只说:

返回通过使用给定格式字符串作为模板初始化的 String 对象,其余参数值将被替换到其中.

解决方案

Swift 中 String 格式的格式说明符与 Objective-C NSString 格式相同,本身与 CFString 格式的相同,并且深埋在 Apple 文档的档案中(两个页面的内容相同,均来自 2002 年或更早):

但是这个文档页面本身并不完整,例如没有提到 flagsprecision 说明符和 width 说明符.实际上,它声称遵循 IEEE printf 规范(第 6 期,2004 版),本身符合 ISO C 标准.所以这些说明符应该与我们在 C printf 中的相同,为 Objective-C 对象添加了 %@ 说明符,并添加了记录不佳的 %D%U%O 说明符和 q 长度修饰符.

说明符

每个转换规范都由%"字符或字符序列%n$"引入.

n 是参数的索引,如:

String(格式: "%2$@ %1$@", "world", "Hello")

格式说明符

%@   Objective-C 对象,打印为 descriptionWithLocale 返回的字符串:如果可用,否则为 description.

实际上,你也可以使用一些 Swift 类型,但它们必须在标准库中定义才能符合 CVarArg 协议,而且我认为它们需要支持桥接 Objective-C 对象:https://developer.apple.com/documentation/foundation/object_runtime/classes_bridged_to_swift_standard_library_value_types.

String(格式: "%@", ["Hello", "world"])

%%    '%' 字符.

String(format: "100%% %@", true.description)

%d, %i   有符号 32 位整数 (int).

String(format: "from %d to %d", Int32.min, Int32.max)

%u, %U, %D   无符号 32 位整数(无符号整数).

String(format: "from %u to %u", UInt32.min, UInt32.max)

%x  无符号 32 位整数 (unsigned int),使用数字 0–9 和小写 a–f 以十六进制打印.

String(format: "from %x to %x", UInt32.min, UInt32.max)

%X   无符号 32 位整数 (unsigned int),使用数字 0–9 和大写 A–F 以十六进制打印.

String(format: "from %X to %X", UInt32.min, UInt32.max)

%o, %O   无符号 32 位整数 (unsigned int),以八进制打印.

String(format: "from %o to %o", UInt32.min, UInt32.max)

%f  64 位浮点数 (double),以十进制表示法打印.产生inf"、infinity"或nan".

String(format: "from %f to %f", Double.leastNonzeroMagnitude, Double.greatestFiniteMagnitude)

%F   64 位浮点数 (double),以十进制表示法打印.产生INF"、INFINITY"或NAN".

String(format: "from %F to %F", Double.leastNonzeroMagnitude, Double.greatestFiniteMagnitude)

%e  64 位浮点数 (double),以科学记数法打印,使用小写 e 来引入指数.

String(format: "from %e to %e", Double.leastNonzeroMagnitude, Double.greatestFiniteMagnitude)

%E  64 位浮点数 (double),以科学记数法打印,使用大写 E 来引入指数.

String(format: "from %E to %E", Double.leastNonzeroMagnitude, Double.greatestFiniteMagnitude)

%g  64 位浮点数(双精度),如果指数小于 –4 或大于等于精度,则按 %e 样式打印,样式中%f 否则.

String(format: "from %g to %g", Double.leastNonzeroMagnitude, Double.greatestFiniteMagnitude)

%G   64 位浮点数 (double),如果指数小于 –4 或大于或等于精度,则以 %E 样式打印,样式中%f 否则.

String(format: "from %G to %G", Double.leastNonzeroMagnitude, Double.greatestFiniteMagnitude)

%c   8 位无符号字符(无符号字符).

String(format: "from %c to %c", "a".utf8.first!, "z".utf8.first!)

%C   16 位 UTF-16 代码单元 (unichar).

String(format: "from %C to %C", "爱".utf16.first!, "终".utf16.first!)

%s   以空结尾的 8 位无符号字符数组.

"Hello world".withCString {字符串(格式:%s",$0)}

%S   以空结尾的 16 位 UTF-16 代码单元数组.

"Hello world".withCString(encodedAs: UTF16.self) {字符串(格式:%S",$0)}

%p   空指针 (void *),以十六进制打印,数字 0–9 和小写 a–f,前导 0x.

var hello = "world"withUnsafePointer(to: &hello) {字符串(格式:%p",$0)}

%n   参数应是一个指向整数的指针,通过调用 fprintf() 函数之一将写入到输出的字节数写入该整数.

n 格式说明符在 Swift 4+ 中似乎不受支持

%a   64 位浮点数 (double),以科学记数法打印,前导 0x 和小数点前一位十六进制数字,使用小写 p 引入指数.

>
String(format: "from %a to %a", Double.leastNonzeroMagnitude, Double.greatestFiniteMagnitude)

%A   64 位浮点数 (double),以科学记数法打印,前导 0X 和小数点前一位十六进制数字,使用大写 P 引入指数.

>
String(format: "from %A to %A", Double.leastNonzeroMagnitude, Double.greatestFiniteMagnitude)

标志

'   a结果的整数部分十进制转换(%i、%d、%u、%f、%F、%g 或 %G)应为用数千个分组字符格式化.对于其他转换行为未定义.非货币分组特征是用过.

' 标志在 Swift 4+ 中似乎不受支持

-   转换的结果应在字段内左对齐.转换是右对齐的,如果未指定此标志.

String(format: "from %-12f to %-12d.", Double.leastNonzeroMagnitude, Int32.max)

+   有符号转换的结果应始终以符号开头(+"或-").转换将开始仅当此标志为负值时才带符号未指定.

String(format: "from %+f to %+d", Double.leastNonzeroMagnitude, Int32.max)

<space>    如果有符号的第一个字符转换不是一个符号,或者如果一个有符号的转换结果没有字符,<space> 应作为结果的前缀.这意味着如果 <space> 和 '+' 标志都出现,则 <space> 标志将被忽略.

String(format: "from % d to % d.", Int32.min, Int32.max)

    指定该值要转换为替代形式.对于 o 转换,它增加了精度(如有必要)强制结果的第一个数字为零.为了x 或 X 转换说明符,非零结果应为 0x(或 0X)以它为前缀.对于 a、A、e、E、f、F、g 和 G 转换说明符,结果应始终包含一个基数字符,即使没有数字跟随基数字符.没有这个标志,一个基数字符仅当后面有数字时,才会出现在这些转换的结果中.对于 g 和 G 转换说明符,不应删除尾随零从通常的结果来看.对于其他转换说明符,行为未定义.

String(format: "from %#a to %#x.", Double.leastNonzeroMagnitude, UInt32.max)

0   对于 d, i, o, u, x, X, a, A, e, E, f, F, g,和 G 转换说明符,前导零(在任何指示之后符号或基数)用于填充到字段宽度;没有空间填充被执行.如果 '0' 和 '-' 标志同时出现,则 '0' 标志是忽略.对于 d、i、o、u、x 和 X 转换说明符,如果 a指定精度,则忽略 '0' 标志.如果 '0' 和 '"标志都出现,分组字符在零之前插入填充.对于其他转换,行为未定义.

String(format: "from %012f to %012d.", Double.leastNonzeroMagnitude, Int32.max)

宽度修饰符

如果转换后的值字节数小于字段宽度,则默认左边用空格填充;如果为字段宽度提供了左调整标志( '-' ),则应在右侧填充它.字段宽度采用星号 ( '*' ) 或十进制整数的形式.

String(format: "from %12f to %*d.", Double.leastNonzeroMagnitude, 12, Int32.max)

精度修饰符

一个可选精度,它给出了 d、i、o、u、x 和 X 转换说明符出现的最小位数;a、A、e、E、f 和 F 转换说明符的基数字符后出现的位数;g 和 G 转换说明符的最大有效位数;或从 s 和 S 转换说明符中的字符串打印的最大字节数.精度采用句点 ( '.' ) 后跟星号 ( '*' ) 或可选的十进制数字字符串的形式,其中空数字字符串被视为零.如果精度与任何其他转换说明符一起出现,则行为未定义.

String(format: "from %.12f to %.*d.", Double.leastNonzeroMagnitude, 12, Int32.max)

长度修饰符

h   长度修饰符指定以下d、o、u、x 或 X 转换说明符适用于短型或无符号简短的论点.

String(format: "from %hd to %hu", CShort.min, CUnsignedShort.max)

hh   长度修饰符指定以下d、o、u、x 或 X 转换说明符适用于有符号字符或无符号字符参数.

String(format: "from %hhd to %hhu", CChar.min, CUnsignedChar.max)

l   长度修饰符指定以下d、o、u、x 或 X 转换说明符适用于 long 或 unsigned长论.

String(format: "from %ld to %lu", CLong.min, CUnsignedLong.max)

ll, q   长度修饰符指定后面的 d、o、u、x 或 X 转换说明符适用于 long long或 unsigned long long 参数.

String(format: "from %lld to %llu", CLongLong.min, CUnsignedLongLong.max)

L   长度修饰符指定以下a、A、e、E、f、F、g 或 G 转换说明符适用于 long双重论证.

我无法在 Swift 4+ 中将 CLongDouble 参数传递给 format

z   长度修饰符指定以下d、o、u、x 或 X 转换说明符适用于 size_t.

String(format: "from %zd to %zu", size_t.min, size_t.max)

t   长度修饰符指定以下d、o、u、x 或 X 转换说明符适用于 ptrdiff_t.

String(format: "from %td to %tu", ptrdiff_t.min, ptrdiff_t.max)

j   长度修饰符指定以下d、o、u、x 或 X 转换说明符适用于 intmax_t 或uintmax_t 参数.

String(format: "from %jd to %ju", intmax_t.min, uintmax_t.max)

In Swift, I can format a String with format specifiers:

// This will return "0.120"
String(format: "%.03f", 0.12)

But the official documentation is not giving any information or link regarding the supported format specifiers or how to build a template similar to "%.03f": https://developer.apple.com/documentation/swift/string/3126742-init

It only says:

解决方案

The format specifiers for String formatting in Swift are the same as those in Objective-C NSString format, itself identical to those for CFString format and are buried deep in the archives of Apple Documentation (same content for both pages, both originally from year 2002 or older):

But this documentation page itself is incomplete, for instance the flags, the precision specifiers and the width specifiers aren't mentioned. Actually, it claims to follow IEEE printf specifications (Issue 6, 2004 Edition), itself aligned with the ISO C standard. So those specifiers should be identical to what we have with C printf, with the addition of the %@ specifier for Objective-C objects, and the addition of the poorly documented %D, %U, %O specifiers and q length modifier.


Specifiers

n is the index of the parameter, like in:

String(format: "%2$@ %1$@", "world", "Hello")

Format Specifiers

Actually, you may also use some Swift types, but they must be defined inside the standard library in order to conform to the CVarArg protocol, and I believe they need to support bridging to Objective-C objects: https://developer.apple.com/documentation/foundation/object_runtime/classes_bridged_to_swift_standard_library_value_types.

String(format: "%@", ["Hello", "world"])
String(format: "100%% %@", true.description)
String(format: "from %d to %d", Int32.min, Int32.max)
String(format: "from %u to %u", UInt32.min, UInt32.max)
String(format: "from %x to %x", UInt32.min, UInt32.max)
String(format: "from %X to %X", UInt32.min, UInt32.max)
String(format: "from %o to %o", UInt32.min, UInt32.max)
String(format: "from %f to %f", Double.leastNonzeroMagnitude, Double.greatestFiniteMagnitude)
String(format: "from %F to %F", Double.leastNonzeroMagnitude, Double.greatestFiniteMagnitude)
String(format: "from %e to %e", Double.leastNonzeroMagnitude, Double.greatestFiniteMagnitude)
String(format: "from %E to %E", Double.leastNonzeroMagnitude, Double.greatestFiniteMagnitude)
String(format: "from %g to %g", Double.leastNonzeroMagnitude, Double.greatestFiniteMagnitude)
String(format: "from %G to %G", Double.leastNonzeroMagnitude, Double.greatestFiniteMagnitude)
String(format: "from %c to %c", "a".utf8.first!, "z".utf8.first!)
String(format: "from %C to %C", "爱".utf16.first!, "终".utf16.first!)
"Hello world".withCString {
    String(format: "%s", $0)
}
"Hello world".withCString(encodedAs: UTF16.self) {
    String(format: "%S", $0)
}
var hello = "world"
withUnsafePointer(to: &hello) {
    String(format: "%p", $0)
}

The n format specifier seems unsupported in Swift 4+

String(format: "from %a to %a", Double.leastNonzeroMagnitude, Double.greatestFiniteMagnitude)
String(format: "from %A to %A", Double.leastNonzeroMagnitude, Double.greatestFiniteMagnitude)

Flags

The ' flag seems unsupported in Swift 4+

String(format: "from %-12f to %-12d.", Double.leastNonzeroMagnitude, Int32.max)
String(format: "from %+f to %+d", Double.leastNonzeroMagnitude, Int32.max)
String(format: "from % d to % d.", Int32.min, Int32.max)
String(format: "from %#a to %#x.", Double.leastNonzeroMagnitude, UInt32.max)
String(format: "from %012f to %012d.", Double.leastNonzeroMagnitude, Int32.max)

Width modifiers

String(format: "from %12f to %*d.", Double.leastNonzeroMagnitude, 12, Int32.max)

Precision modifiers

String(format: "from %.12f to %.*d.", Double.leastNonzeroMagnitude, 12, Int32.max)

Length modifiers

String(format: "from %hd to %hu", CShort.min, CUnsignedShort.max)
String(format: "from %hhd to %hhu", CChar.min, CUnsignedChar.max)
String(format: "from %ld to %lu", CLong.min, CUnsignedLong.max)
String(format: "from %lld to %llu", CLongLong.min, CUnsignedLongLong.max)

I wasn't able to pass a CLongDouble argument to format in Swift 4+

String(format: "from %zd to %zu", size_t.min, size_t.max)
String(format: "from %td to %tu", ptrdiff_t.min, ptrdiff_t.max)
String(format: "from %jd to %ju", intmax_t.min, uintmax_t.max)

这篇关于支持哪些 Swift 字符串格式说明符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-22 13:46