我正在尝试使用旧的printf样式字符串格式化程序从旧的Swift字符串定义新的Swift字符串。
我注意到只要我从Swift字符串文字开始,但不是字符串变量,这样就可以正常工作。
// OK!
String(format:"%s", "hello world".cStringUsingEncoding(NSUTF8StringEncoding))
// ERROR: argument type '[CChar]?' does not conform to expected type 'CVarArgType'
let s = "hello world"
String(format:"%s", s.cStringUsingEncoding(NSUTF8StringEncoding))
为什么会这样?
什么是最好的解决方法?
(请注意我知道但不想使用Cocoa字符串格式化程序%@
。我想要printf样式的格式化代码,因为我实际上要做的就是快速完成使用%-10s
等代码进行脏表格对齐。)
这个问题涉及Swift 2.2。
答案 0 :(得分:1)
不要仅为对齐创建C字符串。对此有一种方法stringByPaddingToLength。
// Swift 2
s.stringByPaddingToLength(10, withString: " ", startingAtIndex: 0)
// Swift 3
s.padding(toLength: 10, withPad: " ", startingAt: 0)
请注意,如果字符串超过10个UTF-16代码单元,它将截断该字符串。
问题在于,Swift中有两个名为cStringUsingEncoding
的方法:
func cStringUsingEncoding(encoding: UInt) -> UnsafePointer<Int8>
,作为NSString的方法func cStringUsingEncoding(encoding: NSStringEncoding) -> [CChar]?
,作为String 如果我们想要一个指针,我们需要确保我们使用的是NSString,而不是String。
在第一个示例中,字符串文字可以是String或NSString,因此编译器选择NSString,因为另一个不起作用。
但在第二个示例中,s
的类型已设置为String,因此选择返回[CChar]?
的方法。
这可以通过强制s
成为NSString来解决这个问题:
let s: NSString = "hello world"
String(format:"%s", s.cStringUsingEncoding(NSUTF8StringEncoding))
答案 1 :(得分:0)
kennytm的回答显然是最好的方式。
但是对于那些仍然想知道如何以错误的方式执行操作并且无需通过NSString即可访问基于Swift String的c字符串的其他人,这似乎也有效(Swift 2.2):
var s:String = "dynamic string"
s.nulTerminatedUTF8.withUnsafeBufferPointer { (buffptr) -> String in
let retval:String = String(format:"%s",buffptr.baseAddress)
return retval
}