3

在尝试使用 Swift 3 在 Linux 中生成随机字符串时,我遇到了 2 个问题。

  1. arc4random_uniform 仅在 BSD 上的 Linux 中不可用。所以我能够摆脱使用 random() 函数。当我生成可变大小的随机数时,这很有效(见下面的代码)

    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 沙箱中运行它时,该功能实际上是有效的

在此处输入图像描述 我假设它也使用linux。我非常困惑和困惑任何帮助将不胜感激。

更新):我只在一个带有单个 swift 文件的 linux 环境中运行了相同的功能,而不是 Vapor swift Web 框架。它有效。正如我在上面的编辑中提到的,它每次都会给我相同的随机字符串。一旦我的构建完成,我仍然需要测试整个项目。但除此之外,我需要知道 random() 函数是否真的每次都会给我一些新的东西,而不是同样的废话。

4

4 回答 4

3

1) 总是相同的号码

您必须设置一次种子才能从以下位置获取“随机”数字random()

randomSeed(Int(Date().timeIntervalSince1970)

手册页

如果没有提供种子值,则 random() 函数自动使用值 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
}
于 2017-01-08T07:57:28.070 回答
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
 }  
于 2017-01-08T08:00:39.430 回答
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 上。

于 2017-10-11T17:17:28.790 回答
0

斯威夫特 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]
}
于 2018-10-17T12:50:35.393 回答