【发布时间】:2016-11-01 09:08:09
【问题描述】:
我想做的事情在 C/C++、Java 和许多其他语言中非常简单。我想做的就是能够指定字符串的宽度,类似于:
printf("%-15s", var);
这将创建 15 个字符的字段宽度。我做了很多谷歌搜索。我尝试过以各种方式使用COpaquepointer 和String(format:,但都没有成功。任何建议将不胜感激。谷歌搜索时我可能会错过一些东西。
【问题讨论】:
我想做的事情在 C/C++、Java 和许多其他语言中非常简单。我想做的就是能够指定字符串的宽度,类似于:
printf("%-15s", var);
这将创建 15 个字符的字段宽度。我做了很多谷歌搜索。我尝试过以各种方式使用COpaquepointer 和String(format:,但都没有成功。任何建议将不胜感激。谷歌搜索时我可能会错过一些东西。
【问题讨论】:
您可以使用withCString 将字符串快速转换为字节数组(技术上是UnsafePointer<Int8>):
let str = "Hello world"
let formatted = str.withCString { String(format: "%-15s", $0) }
print("'\(formatted)'")
【讨论】:
你最好自己做
let str0 = "alpha"
let length = 20
// right justify
var str20r = String(count: (length - str0.characters.count), repeatedValue: Character(" "))
str20r.appendContentsOf(str0)
// " alpha"
// left justify
var str20l = str0
str20l.appendContentsOf(String(count: (length - str0.characters.count), repeatedValue: Character(" ")))
// "alpha "
如果你需要一些“更通用”的东西
func formatString(str: String, fixLenght: Int, spacer: Character = Character(" "), justifyToTheRigth: Bool = false)->String {
let c = str.characters.count
let start = str.characters.startIndex
let end = str.characters.endIndex
var str = str
if c > fixLenght {
switch justifyToTheRigth {
case true:
let range = start.advancedBy(c - fixLenght)..<end
return String(str.characters[range])
case false:
let range = start..<end.advancedBy(fixLenght - c)
return String(str.characters[range])
}
} else {
var extraSpace = String(count: fixLenght - c, repeatedValue: spacer)
if justifyToTheRigth {
extraSpace.appendContentsOf(str)
return extraSpace
} else {
str.appendContentsOf(extraSpace)
return str
}
}
}
let str = "ABCDEFGH"
let s0 = formatString(str, fixLenght: 3)
let s1 = formatString(str, fixLenght: 3, justifyToTheRigth: true)
let s2 = formatString(str, fixLenght: 10, spacer: Character("-"))
let s3 = formatString(str, fixLenght: 10, spacer: Character("-"), justifyToTheRigth: true)
print(s0)
print(s1)
print(s2)
print(s3)
打印出来的
ABC
FGH
ABCDEFGH--
--ABCDEFGH
【讨论】:
问题在于 Swift 字符串具有可变大小的元素,因此“15 个字符”是什么是模棱两可的。这对于简单的字符串来说是一个令人沮丧的根源——但在处理表情符号、区域标识符、连字等时会使语言更加精确。
您可以将 Swift 字符串转换为 C 字符串并使用普通格式化程序(请参阅 Santosh 的回答)。处理字符串的“Swift”方式是从Characters 集合的起始索引开始,前进N 次。例如:
let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
let index = alphabet.characters.startIndex.advancedBy(14) // String.CharacterView.Index
let allChars = alphabet.characters.prefixThrough(index) // String.CharacterView
print(String(allChars)) // "ABCDEFGHIJKLMNO\n"
如果你想强制填充,你可以使用这样的方法:
extension String {
func formatted(characterCount characterCount:Int) -> String {
if characterCount < characters.count {
return String(characters.prefixThrough(characters.startIndex.advancedBy(characterCount - 1)))
} else {
return self + String(count: characterCount - characters.count, repeatedValue: " " as Character)
}
}
}
let abc = "ABC"
let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
print("!\(abc.formatted(characterCount: 15))!")
// "!ABC !\n"
print("!\(alphabet.formatted(characterCount: 15))!")
// "!ABCDEFGHIJKLMNOP!\n"
【讨论】:
你试过了吗?
let string1 = "string1"
let string2 = "string2"
let formattedString = String(format: "%-15s - %s",
COpaquePointer(string1.cStringUsingEncoding(NSUTF8StringEncoding)!),
COpaquePointer(string2.cStringUsingEncoding(NSUTF8StringEncoding)!)
)
print(formattedString)
//string1 - string2
【讨论】:
我们现在有很多有趣的答案。谢谢大家。我写了以下内容:
func formatLeftJustifiedWidthSpecifier(stringToChange: String, width: Int) -> String {
var newString: String = stringToChange
newString = newString.stringByPaddingToLength(width, withString: " ", startingAtIndex: 0)
return newString
}
【讨论】:
stringByPaddingToLength? , (3) : String 是不必要的, (4) 为什么分配给newString 只是为了立即覆盖值?
一方面 %@ 用于格式化字符串对象:
import Foundation
var str = "Hello"
print(String(format: "%@", str))
但它不支持宽度修饰符:
print(String(format: "%-15@", str))
仍会打印未填充的文本:
"Hello\n"
但是有一个修饰符 %s 似乎可以与 CStrings 一起使用:
var cstr = (str as NSString).utf8String //iOS10+ or .UTF8String otherwise
print(String(format: "%-15s", cstr!))
输出:
"Hello \n"
一件好事是您可以使用与 NSLog 相同的格式规范:
NSLog("%-15s", cstr!)
【讨论】: