Im having 2 problems when trying to generate a random string in Linux with Swift 3.
尝试使用Swift 3在Linux中生成随机字符串时遇到2个问题。
-
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)
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}#elsefor _ in 0..<5{ place *= 10 let randomNumber = Int(arc4random_uniform(10)) finalNumber += randomNumber * place}#endif return finalNumber}
And that WORKS. Edit: it works but it gives me the same number every time :(
那就是工作。编辑:它的工作原理,但它每次给我相同的数字:(
- When trying to generate random alphanumeric string I'm limited to using Swift String and NOT NSSTRING. Linux throws this error
当试图生成随机字母数字字符串时,我只限于使用Swift String而不是NSSTRING。 Linux抛出此错误
original pre Linux block of code:
原始的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 }
And the actual error I get when using above code
以及使用上面的代码时得到的实际错误
error: cannot convert value of type 'NSString' to type 'String' in coercion randomString += NSString(characters: &nextChar, length: 1) as String
modified for linux block of code.
修改为linux代码块。
func randomString(_ length: Int) -> String {let letters : String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"let len = letters.characters.countvar 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}
but this time the error is weird it only says Illegal instruction with no extra information. I ran the docker container in interactive mode and i saw my server running and printing out when calling other functions etc.
但这一次错误是奇怪的,它只是说没有额外信息的非法指令。我以交互模式运行了docker容器,当我调用其他函数等时,我看到我的服务器正在运行并打印出来。
but the thing is the function actually WORKS when i ran it in IBMs swiftsandbox
但是当我在IBM的swiftsandbox中运行它时,实际上是函数
and I'm assuming its using linux also. Im very stuck and confused any help would be greatly appreciated.
我也假设它也使用linux。我非常困惑和困惑任何帮助将不胜感激。
(UPDATE): I ran the same function in just a linux env with a single swift file and not the Vapor swift web framework. and it works. As mentioned in my edit above it gives me the same random string everytime. I will still have to test the entire project once my build finishes. But besides that i need to know if the random() function will actually give me something new each time instead of the same crap.
(更新):我在一个linux env中使用单个swift文件运行相同的功能,而不是Vapor swift Web框架。它的工作原理。正如我在上面的编辑中提到的,它每次都给我相同的随机字符串。一旦我的构建完成,我仍然需要测试整个项目。但除此之外,我需要知道random()函数是否实际上每次给我一些新东西而不是相同的废话。
4 个解决方案
#1
3
Figured it out.
弄清楚了。
So the answer to the repeating random number/string was to just add this line before i called the random() function
所以重复随机数/字符串的答案就是在我调用random()函数之前添加这一行
srand(UInt32(time(nil)))
and I'm assuming thats what fixed the illegal instruction also. Because i don't recall changing anything else.
而且我假设那也是修正非法指令的原因。因为我不记得改变其他任何东西。
Needless to say here is my final result
不用说这是我的最终结果
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 }
#2
3
1) Always the same number
1)总是相同的数字
You have to set a seed once to get "random" numbers from random()
:
您必须设置一次种子以从random()获得“随机”数字:
randomSeed(Int(Date().timeIntervalSince1970)
If no seed value is provided, the random() function is automatically seeded with a value of 1.
如果未提供种子值,则random()函数将自动播种,值为1。
As the seed is always the same (1), you always get the same sequence of "random" numbers.
由于种子总是相同(1),因此总是得到相同的“随机”数字序列。
2) Alphanumeric string
2)字母数字字符串
To create your string without using NSString
:
要在不使用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}
#3
0
I copied and pasted your code exactly, and it doesn't compile.
我完全复制并粘贴了你的代码,但它没有编译。
fatal error: Can't form a Character from an empty String
致命错误:无法从空字符串形成字符
Here's an alternative method:
// Keep at top of your code (outside of functions)#if os(Linux) srandom(UInt32(time(nil)))#endiffunc 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 itselflet chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"print(getRandomString(chars, 10))
This works for me on Ubuntu.
这适用于Ubuntu。
#4
0
Swift 4.2, Ubuntu 16.04
Swift 4.2,Ubuntu 16.04
let letters : String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"let len = letters.countvar randomString:String = ""for _ in 0 ..< length { let rand = Int.random(in: 0..<len) randomString += letters.map { String($0) }[rand]}
#1
3
Figured it out.
弄清楚了。
So the answer to the repeating random number/string was to just add this line before i called the random() function
所以重复随机数/字符串的答案就是在我调用random()函数之前添加这一行
srand(UInt32(time(nil)))
and I'm assuming thats what fixed the illegal instruction also. Because i don't recall changing anything else.
而且我假设那也是修正非法指令的原因。因为我不记得改变其他任何东西。
Needless to say here is my final result
不用说这是我的最终结果
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 }
#2
3
1) Always the same number
1)总是相同的数字
You have to set a seed once to get "random" numbers from random()
:
您必须设置一次种子以从random()获得“随机”数字:
randomSeed(Int(Date().timeIntervalSince1970)
If no seed value is provided, the random() function is automatically seeded with a value of 1.
如果未提供种子值,则random()函数将自动播种,值为1。
As the seed is always the same (1), you always get the same sequence of "random" numbers.
由于种子总是相同(1),因此总是得到相同的“随机”数字序列。
2) Alphanumeric string
2)字母数字字符串
To create your string without using NSString
:
要在不使用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}
#3
0
I copied and pasted your code exactly, and it doesn't compile.
我完全复制并粘贴了你的代码,但它没有编译。
fatal error: Can't form a Character from an empty String
致命错误:无法从空字符串形成字符
Here's an alternative method:
// Keep at top of your code (outside of functions)#if os(Linux) srandom(UInt32(time(nil)))#endiffunc 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 itselflet chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"print(getRandomString(chars, 10))
This works for me on Ubuntu.
这适用于Ubuntu。
#4
0
Swift 4.2, Ubuntu 16.04
Swift 4.2,Ubuntu 16.04
let letters : String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"let len = letters.countvar randomString:String = ""for _ in 0 ..< length { let rand = Int.random(in: 0..<len) randomString += letters.map { String($0) }[rand]}