在andom索引处插入字符串不能正常工作

ric*_*brz 0 arrays numbers generator ios swift

我正在研究一个随机密码生成器,我希望有一个用户可以输入的基本字符串,并在基本字符串内部或周围生成随机字符.我的问题是,只要它用基本字符串生成随机字符,它们就会插入前面(第0个索引).这是我的代码:

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var baseStringTextField: UITextField!
    @IBOutlet weak var lowerCaseSwitch: UISwitch!
    @IBOutlet weak var upperCaseSwitch: UISwitch!
    @IBOutlet weak var numberSwitch: UISwitch!
    @IBOutlet weak var numberOfCharactersSlider: UISlider!
    @IBOutlet weak var numberOfCharsLabel: UILabel!

    let lower = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t","u","v","w", "x", "y", "z"]
    let upper = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]
    let numbers = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]

    let lowerUpper = ["a", "b", "c", "d", "e", "f", "g",
        "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
        "u", "v", "w", "x", "y", "z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z",]

    let lowerNumber = ["a", "b", "c", "d", "e", "f", "g",
        "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
        "u", "v", "w", "x", "y", "z","1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]

    let upperNumber = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]

    let all = ["a", "A" ,"b", "B", "c", "C", "d", "D", "e", "E" , "f", "F", "g", "G",  "h", "H", "i", "I",  "j", "J" ,"k", "K", "l", "L" ,"m", "M" , "n", "N" ,"o", "O", "p", "P",  "q", "Q", "r", "R", "s", "S", "t", "T", "u", "U", "v", "V", "w", "W", "x","X", "y", "Y" , "z", "Z", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]

    var generatedString = [""]


    func generateLower(){
        srandom(UInt32(time(nil)))
        var baseString:[String] = Array(arrayLiteral: baseStringTextField.text)
        for var i = 0; i < Int(roundf(numberOfCharactersSlider.value)) ; ++i{
            var char = lower[Int(arc4random_uniform(26))]
            var count_ = baseString.count
            var baseStringText = baseStringTextField.text
            var randIndex:Int = Int(arc4random_uniform(UInt32(count_ + count(baseStringText.utf16))))
            baseString.insert(char, atIndex: randIndex)
        }
        generatedString = baseString
        generatedStringLabel.text = "".join(generatedString)
    }

    func generateUpper(){
        srandom(UInt32(time(nil)))
        var baseString:[String] = Array(arrayLiteral: baseStringTextField.text)
        for var i = 0; i < Int(roundf(numberOfCharactersSlider.value)) ; ++i{
            var char = upper[Int(arc4random_uniform(26))]
            var count_ = baseString.count
            var baseStringText = baseStringTextField.text
            var randIndex:Int = Int(arc4random_uniform(UInt32(count_ + count(baseStringText.utf16))))
            baseString.insert(char, atIndex: randIndex)
        }
        generatedString = baseString
        generatedStringLabel.text = "".join(generatedString)
    }

    func generateNumber(){
        srandom(UInt32(time(nil)))
        var baseString:[String] = Array(arrayLiteral: baseStringTextField.text)
        for var i = 0; i < Int(roundf(numberOfCharactersSlider.value)) ; ++i{
            var char = numbers[Int(arc4random_uniform(10))]
            var count_ = baseString.count
            var baseStringText = baseStringTextField.text
            var randIndex:Int = Int(arc4random_uniform(UInt32(count_ + count(baseStringText.utf16))))
            baseString.insert(char, atIndex: randIndex)
        }
        generatedString = baseString
        generatedStringLabel.text = "".join(generatedString)
    }

    func generateLowerAndUpper(){
        srandom(UInt32(time(nil)))
        var baseString:[String] = Array(arrayLiteral: baseStringTextField.text)
        for var i = 0; i < Int(roundf(numberOfCharactersSlider.value)) ; ++i{
            var count_ = baseString.count
            var baseStringText = baseStringTextField.text
            var randIndex:Int = Int(arc4random_uniform(UInt32(count_ + count(baseStringText.utf16))))
                var char = lowerUpper[Int(arc4random_uniform(52))]
                baseString.insert(char, atIndex: randIndex)
        }
        generatedString = baseString
        generatedStringLabel.text = "".join(generatedString)
    }

    func generateLowerAndNumber(){
        var baseString:[String] = Array(arrayLiteral: baseStringTextField.text)
        srandom(UInt32(time(nil)))
        for var i = 0; i < Int(roundf(numberOfCharactersSlider.value)) ; ++i{
            var count_ = baseString.count
            var baseStringText = baseStringTextField.text
            var randIndex:Int = Int(arc4random_uniform(UInt32(count_ + count(baseStringText.utf16))))
                var char = lowerNumber[Int(arc4random_uniform(36))]
                baseString.insert(char, atIndex: randIndex)
        }
        generatedString = baseString
        generatedStringLabel.text = "".join(generatedString)
    }

    func generateUpperAndNumber(){
        srandom(UInt32(time(nil)))
        var baseString:[String] = Array(arrayLiteral: baseStringTextField.text)
        for var i = 0; i < Int(roundf(numberOfCharactersSlider.value)) ; ++i{
            var count_ = baseString.count
            var baseStringText = baseStringTextField.text
            var randIndex:Int = Int(arc4random_uniform(UInt32(count_ + count(baseStringText.utf16))))
                var char = upperNumber[Int(arc4random_uniform(36))]
                baseString.insert(char, atIndex: randIndex)
        }
        generatedString = baseString
        generatedStringLabel.text = "".join(generatedString)
    }

    func generateAll(){
        srandom(UInt32(time(nil)))
        var baseString:[String] = Array(arrayLiteral: baseStringTextField.text)
        for var i = 0; i < Int(roundf(numberOfCharactersSlider.value)) ; ++i{
            var count_ = baseString.count
            println(count_)
            var randIndex:Int = Int(arc4random_uniform(UInt32(count_)))
            var char = all[Int(arc4random_uniform(62))]
            baseString.insert(char, atIndex: randIndex)
        }
        generatedString = baseString
        generatedStringLabel.text = "".join(generatedString)
    }

    @IBAction func generateString(sender: UIButton) {
        if(lowerCaseSwitch.on && upperCaseSwitch.on && numberSwitch.on){
            generateAll()
        }else if(lowerCaseSwitch.on && upperCaseSwitch.on == false && numberSwitch.on == false){
            generateLower()
        }else if(upperCaseSwitch.on && lowerCaseSwitch.on == false && numberSwitch.on == false){
            generateUpper()
        }else if(numberSwitch.on && lowerCaseSwitch.on == false  && upperCaseSwitch.on == false){
            generateNumber()
        }else if(lowerCaseSwitch.on && upperCaseSwitch.on && numberSwitch.on == false){
            generateLowerAndUpper()
        }else if(lowerCaseSwitch.on && numberSwitch.on && upperCaseSwitch.on == false){
            generateLowerAndNumber()
        }else if(upperCaseSwitch.on && numberSwitch.on && lowerCaseSwitch.on == false){
            generateUpperAndNumber()
        }
    }

    @IBAction func copyButtonPressed(sender: UIButton) {
        UIPasteboard.generalPasteboard().string = "".join(generatedString)
}
    override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
        view.endEditing(true)
        super.touchesBegan(touches, withEvent: event)
    }
}
Run Code Online (Sandbox Code Playgroud)

任何帮助,将不胜感激.谢谢!

Air*_*ity 5

您的代码将非常难以调试,因为它将许多不同的东西混合在一起 - 从数组中获取随机元素,从随机元素构建字符串,更新UI,从UI获取设置以控制代码.

你会发现在第一次尝试时编写正确的代码要容易得多,并且如果你养成了将你需要做的事情分解成多个构建块的习惯,那就让自己远离调试地狱.

要构建哪些构建块只是练习中的一个问题,但是如果您发现自己重复使用相同的相同代码并且一次又一次地重复相同的代码,就像您在各种generateXXX函数中所做的那样- 这些是的方式,打破了你的代码的例子是不是有用.

例如,您需要一个生成给定长度密码的函数,可选择包括各种字符.为此,您需要一个从数组(或任何集合)中获取随机字符的函数.为此,您需要一个将系统生成的随机数转换为集合索引的函数.那些可能会成为好的构建块.

所以,一个转换的函数arc4random_uniform(顺便说一下,没有必要调用srand,arc4random种子本身):

(以下所有的雨燕2.0的代码,但除非你打算出货东西产量不到3个月,特别是如果你正在学习斯威夫特,我强烈建议升级,因为它是容易比1.2使用,你最终必须升级,离开的时间越长就会很痛苦)

/// Version of arc4random that works for any integer type. Kinda ugly unfortunately.
func arc4random_uniform<In: _SignedIntegerType, Out: _SignedIntegerType>(upto: In) -> Out 
{
    precondition(upto < numericCast(UInt32.max),"Range too big for arc4random")
    return numericCast(Darwin.arc4random_uniform(numericCast(upto.toIntMax())))
}
Run Code Online (Sandbox Code Playgroud)

然后是一个从集合中获取随机元素的函数.这通常适用于任何集合类型,但您可以为数组编写它,因为如果这就是您所需要的,这将更容易做到:

/// Fetch a random element from any collection that supports random access
extension CollectionType where Index: RandomAccessIndexType {
    var randomElement: Generator.Element {
        guard !isEmpty else { fatalError("Collection cannot be empty") }
        return self[startIndex.advancedBy(arc4random_uniform(count))]
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,为您可能想要包含的不同类型的字符设置一个选项:

/// A set of options for controlling which characters to include in a password
struct CharacterOptions: OptionSetType {
    let rawValue: Int
    init(rawValue: Int) { self.rawValue = rawValue }

    static let LowerCase = CharacterOptions(rawValue: 1)
    static let UpperCase = CharacterOptions(rawValue: 2)
    static let Numbers = CharacterOptions(rawValue: 4)

    /// An array of the full set of characters based on the options set
    var characters: [Character] {
        let lower = Array("abcdefghijklmnop".characters)
        let upper = Array("ABCDEFGHIKKLMNOP".characters)
        let numbers = Array("1234567890".characters)

        // this could be done so much more efficiently if only
        // LazyRandomAccessCollection supported flatMap
        return (self.contains(.LowerCase) ? lower   : [])
             + (self.contains(.UpperCase) ? upper   : [])
             + (self.contains(.Numbers)   ? numbers : [])
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,将它们组合成一个生成密码的函数:

func generatePassword(length: Int, options: CharacterOptions) -> String {
    let sources: [Character] = options.characters

    let characters = (0..<length).map { _ in
        sources.randomElement
    }

    return String(characters)
}

generatePassword(10, options: [.LowerCase, .UpperCase])
Run Code Online (Sandbox Code Playgroud)

然后,当您构建此随机密码生成函数时,您应该从视图控制器中调用它.但是你不必 - 你可以单独调用它,这使得测试和检查它的工作和调试变得容易得多.独立功能也可以独立测试.