随机字母数字字符串 Linux Swift 3

3

我在试图使用Swift 3在Linux上生成随机字符串时遇到了两个问题。

  1. arc4random_uniform is not available in Linux only on BSD. SO i was able to get away with using random() function. And this worked when i was generating random numbers of a variable size (See code below)

    func generateRandomNumber() -> Int
    {
       var place = 1
    
       var finalNumber = 0;
    
    #if os(Linux)
    for _ in 0..<5
    {
        place *= 10
    
        let randomNumber = Int(random() % 10) + 1
    
        finalNumber += randomNumber * place
    }
    #else
    for _ in 0..<5
    {
        place *= 10
    
        let randomNumber = Int(arc4random_uniform(10))
    
        finalNumber += randomNumber * place
    }
    #endif
    
      return finalNumber
    }
    

这很有效。

  1. 当我尝试生成随机的字母数字字符串时,我只能使用Swift String而不能使用NSString。在Linux上会抛出此错误。

原始的Linux代码块如下:

   func randomString(_ length: Int) -> String
   {

      let letters : NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
      let len = UInt32(letters.length)

      var randomString = ""

      for _ in 0 ..< length {
    let rand = arc4random_uniform(len)
    var nextChar = letters.character(at: Int(rand))
    randomString += NSString(characters: &nextChar, length: 1) as String
      }

       return randomString
    }

当使用上述代码时,我实际得到的错误信息如下:

    error: cannot convert value of type 'NSString' to type 'String' in coercion
        randomString += NSString(characters: &nextChar, length: 1) as String

修改适用于Linux的代码块。

    func randomString(_ length: Int) -> String
    {

let letters : String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
let len = letters.characters.count

var randomString = ""

#if os(Linux)

    for _ in 0..<length
    {
        let randomValue = (random() % len) + 1

        randomString += "\(letters[letters.index(letters.startIndex, offsetBy: Int(randomValue))])"
    }

    #else
    for _ in 0 ..< length
    {
        let rand = arc4random_uniform(UInt32(len))

        randomString += "\(letters[letters.index(letters.startIndex, offsetBy: Int(rand))])"
    }
    #endif


      return randomString
}          

但这次错误非常奇怪,它只显示非法指令,没有额外的信息。我以交互模式运行docker容器,当调用其他函数时,我看到我的服务器正在运行和打印输出。

但问题是,当我在IBM的Swift沙箱中运行该函数时,它实际上是有效的。

enter image description here 我假设它也在使用Linux。我被卡住了,感到困惑,任何帮助将不胜感激。

(更新): 我在单个Swift文件和不使用Vapor Swift web框架的Linux环境下运行了相同的函数,也是有效的。如我上面的编辑所述,它每次都会给我相同的随机字符串。一旦我的构建完成,我仍然需要测试整个项目。除此之外,我需要知道random()函数是否会每次都给我新的内容而不是相同的垃圾。

4个回答

3

1)始终是相同的数字

您需要设置一次种子才能从random()获得“随机”数字:

randomSeed(Int(Date().timeIntervalSince1970)

手册页面:

如果未提供种子值,则随机()函数将自动用值1进行种子处理。

由于种子始终相同(1),因此您始终会得到相同的“随机”数字序列。

2) 字母数字字符串

要创建不使用NSString的字符串:

func randomString(length: Int) -> String {

    let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    let len = UInt32(letters.characters.count)

    var randomString = ""

    for _ in 0 ..< length {
        let rand = myCustomRandom(len)
        let randIndex = letters.index(letters.startIndex, offsetBy: Int(rand))
        let nextChar = letters[randIndex]
        randomString += String(nextChar)
    }

    return randomString
}

谢谢您的第一个回答,但是您提供的字母数字字符串部分不支持arc4random_uniform,因为它在Linux上。 - Andrew Edwards
当然。您必须使用种子“random()”。更新的答案。 - shallowThought

3

我已经理解了。

所以,对于重复的随机数字/字符串的问题,只需要在调用random()函数之前添加这一行代码即可:

srand(UInt32(time(nil)))

我假设这也是修复非法指令的原因。因为我不记得改变了其他任何东西。
毋庸置疑,以下是我的最终结果。
 func generateRandomNumber() -> Int
 {
    var place = 1

    var finalNumber = 0;

    #if os(Linux)

    srand(UInt32(time(nil)))

    for _ in 0..<5
    {
        place *= 10

        let randomNumber = Int(random() % 10) + 1

        finalNumber += randomNumber * place
    }
    #else
    for _ in 0..<5
    {
        place *= 10

        let randomNumber = Int(arc4random_uniform(10))

        finalNumber += randomNumber * place
    }
    #endif

     return finalNumber
 }



 func randomString(_ length: Int) -> String
 {

    let letters : String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    let len = letters.characters.count

    var randomString = ""

    #if os(Linux)

    srand(UInt32(time(nil)))

   for _ in 0..<length
   {
     let randomValue = (random() % len) + 1

     randomString += "\(letters[letters.index(letters.startIndex, offsetBy: Int(randomValue))])"
   }

   #else
  for _ in 0 ..< length
  {
     let rand = arc4random_uniform(UInt32(len))

     randomString += "\(letters[letters.index(letters.startIndex, offsetBy: Int(rand))])"
  }
  #endif

   return randomString
 }  

0

Swift 4.2,Ubuntu 16.04

let letters : String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
let len = letters.count
var randomString:String = ""
for _ in 0 ..< length {
   let rand = Int.random(in: 0..<len)
   randomString += letters.map { String($0) }[rand]
}

0

我完全复制并粘贴了你的代码,但它无法编译。

致命错误:无法从空字符串中形成字符

这里有一种替代方法:

// Keep at top of your code (outside of functions)
#if os(Linux)
    srandom(UInt32(time(nil)))
#endif


func getRandomNumber(_ min: Int, _ max: Int) -> Int {
    #if os(Linux)
        return Int(random() % max) + min
    #else
        return Int(arc4random_uniform(UInt32(max)) + UInt32(min))
    #endif
}


func getRandomString(_ chars: String, _ length: Int) -> String {
    var str = ""

    for _ in 1...length {
        str.append(chars.itemOnStartIndex(advancedBy: getRandomNumber(0, chars.count - 1)))
    }

    return str
}


// Best practice to define this outside of the function itself
let chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
print(getRandomString(chars, 10))

在Ubuntu上这对我有效。


哦,看起来不错。是因为它使用了Swift 4吗? - Andrew Edwards
不,这并没有使用任何Swift 4的特性。;) - gavanon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接