Заполнение быстрой строки для печати

Я пытаюсь распечатать список строк, заполненных одинаковой шириной.

В C я бы использовал нечто вроде printf("%40s", cstr),, где cstr - строка C.

В Swift лучшее, что я мог придумать, это:

line += String(format: "%40s",string.cStringUsingEncoding(<someEncoding>))

Есть ли лучший способ?

Ответ 1

NSString имеет метод stringByPaddingToLength::

line += string.stringByPaddingToLength(40, withString: " ", startingAtIndex: 0)

Ответ 2

В Swift 3 вы можете использовать:

let str = "Test string"
let paddedStr = str.padding(toLength: 20, withPad: " ", startingAt: 0)

Строка результата: "Test string "

Если вам нужно добавить слева текст (выровнять по правому краю), вы можете написать следующую функцию как расширение для String:

extension String {
    func leftPadding(toLength: Int, withPad character: Character) -> String {
        let newLength = self.characters.count
        if newLength < toLength {
            return String(repeatElement(character, count: toLength - newLength)) + self
        } else {
            return self.substring(from: index(self.startIndex, offsetBy: newLength - toLength))
        }
    }
}

Так что если вы напишите:

let str = "Test string"
let paddedStr = str.leftPadding(toLength: 20, withPad: " ")

Строка результата: " Test string"

В Swift 4.1 метод substring устарел, и есть ряд новых методов для получения подстроки. prefix, suffix или подписка String с Range<String.Index>.

Для предыдущего расширения мы можем использовать метод suffix для достижения того же результата. Поскольку suffix метод возвращает String.SubSequence, его необходимо преобразовать в String прежде чем он будет возвращен.

extension String {
    func leftPadding(toLength: Int, withPad character: Character) -> String {
        let stringLength = self.count
        if stringLength < toLength {
            return String(repeatElement(character, count: toLength - stringLength)) + self
        } else {
            return String(self.suffix(toLength))
        }
    }
}

Ответ 3

Поместите весь строковый формат в extension и повторно используйте его там, где хотите.

extension String {
    func padding(length: Int) -> String {
        return self.stringByPaddingToLength(length, withString: " ", startingAtIndex: 0)
    }

    func padding(length: Int, paddingString: String) -> String {
        return self.stringByPaddingToLength(length, withString: paddingString, startingAtIndex: 0)
    }
}

var str = "str"
print(str.padding(10)) // "str       "
print(str.padding(10, paddingString: "+")) // "str+++++++"

Ответ 4

extension RangeReplaceableCollection where Self: StringProtocol {
    func paddingToLeft(upTo length: Int, using element: Element = " ") -> SubSequence {
        return repeatElement(element, count: Swift.max(0, length-count)) + suffix(Swift.max(count, count-length))
    }
}

"123".paddingToLeft(upTo: 5)              //  "  123"
"123".paddingToLeft(upTo: 5, using: "0")  //  "00123"
"123".paddingToLeft(upTo: 3, using: "0")  //    "123"
"$199.99".dropLast(3).paddingToLeft(upTo: 10, using: "_")  //  "______$199"

Ответ 5

Следующие две функции возвращают строку, дополненную до заданной ширины, с выравниванием по левому или правому краю. Это чистый Swift 4, ни строки NSString, ни строки Си. Вы можете выбрать, будет ли обрезана строка длиннее ширины отступа или нет.

extension String {
    func rightJustified(width: Int, truncate: Bool = false) -> String {
        guard width > count else {
            return truncate ? String(suffix(width)) : self
        }
        return String(repeating: " ", count: width - count) + self
    }

    func leftJustified(width: Int, truncate: Bool = false) -> String {
        guard width > count else {
            return truncate ? String(prefix(width)) : self
        }
        return self + String(repeating: " ", count: width - count)
    }
}