我想调用一个方法,将长度传递给它,并让它生成一个随机的字母数字字符串。
是否有任何实用库可以提供这些类型的函数?
我想调用一个方法,将长度传递给它,并让它生成一个随机的字母数字字符串。
是否有任何实用库可以提供这些类型的函数?
这是一个快速而简单的实现。尚未经过测试。
NSString *letters = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
-(NSString *) randomStringWithLength: (int) len {
NSMutableString *randomString = [NSMutableString stringWithCapacity: len];
for (int i=0; i<len; i++) {
[randomString appendFormat: @"%C", [letters characterAtIndex: arc4random_uniform([letters length])]];
}
return randomString;
}
虽然不完全符合您的要求,但仍然有用:
[[NSProcessInfo processInfo] globallyUniqueString]
样例输出:
450FEA63-2286-4B49-8ACC-9822C7D4356B-1376-00000239A4AC4FD5
NSString *alphabet = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXZY0123456789";
NSMutableString *s = [NSMutableString stringWithCapacity:20];
for (NSUInteger i = 0U; i < 20; i++) {
u_int32_t r = arc4random() % [alphabet length];
unichar c = [alphabet characterAtIndex:r];
[s appendFormat:@"%C", c];
}
alphabet
的长度吗?它是常量,不会随循环而改变。 - jv42NSArray
缓存了它的 length
,不应该成为性能瓶颈。 - Pascal你肯定可以把这个缩短一点:
+(NSString*)generateRandomString:(int)num {
NSMutableString* string = [NSMutableString stringWithCapacity:num];
for (int i = 0; i < num; i++) {
[string appendFormat:@"%C", (unichar)('a' + arc4random_uniform(26))];
}
return string;
}
如果您只愿意使用十六进制字符,那么最简单的选择是生成UUID:
NSString *uuid = [NSUUID UUID].UUIDString;
示例输出:16E3DF0B-87B3-4162-A1A1-E03DB2F59654
。
如果您想要一个更小的随机字符串,可以只取前8个字符。
这是一个版本4的UUID,这意味着第3组和第4组中的第一个字符不是随机的(它们将始终是4
和8
、9
、A
或B
中的一个)。
字符串中的其他每个字符都是完全随机的,您可以每秒生成数百万个UUID,数百年而不用太担心重复生成相同的UUID。
NSString *uuid = [UUID UUID]
。 - orkodenJeff B的回答的一个分类版本。
NSString+Random.h
#import <Foundation/Foundation.h>
@interface NSString (Random)
+ (NSString *)randomAlphanumericStringWithLength:(NSInteger)length;
@end
NSString+Random.m
#import "NSString+Random.h"
@implementation NSString (Random)
+ (NSString *)randomAlphanumericStringWithLength:(NSInteger)length
{
NSString *letters = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
NSMutableString *randomString = [NSMutableString stringWithCapacity:length];
for (int i = 0; i < length; i++) {
[randomString appendFormat:@"%C", [letters characterAtIndex:arc4random() % [letters length]]];
}
return randomString;
}
@end
你也可以生成UUID。虽然不是真正的随机数,但它们复杂而独特,使它们在大多数情况下看起来像随机数。将其生成为字符串,然后取一个字符范围等于传递的长度。
Swift
func randomStringWithLength(length: Int) -> String {
let alphabet = "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
let upperBound = UInt32(count(alphabet))
return String((0..<length).map { _ -> Character in
return alphabet[advance(alphabet.startIndex, Int(arc4random_uniform(upperBound)))]
})
}
upperBound
替换了硬编码的 64
。我在块外计算 upperBound
,因为我认为这样性能更好。 - ma11hew28这里有一种不同的解决方法。不使用预定义的字符字符串,而是可以在整数和字符之间进行转换,并生成一个动态的字符列表来选择。它非常简洁和快速,但需要更多的代码。
int charNumStart = (int) '0';
int charNumEnd = (int) '9';
int charCapitalStart = (int) 'A';
int charCapitalEnd = (int) 'Z';
int charLowerStart = (int) 'a';
int charLowerEnd = (int) 'z';
int amountOfChars = (charNumEnd - charNumStart) + (charCapitalEnd - charCapitalStart) + (charLowerEnd - charLowerStart); // amount of the characters we want.
int firstGap = charCapitalStart - charNumEnd; // there are gaps of random characters between numbers and uppercase letters, so this allows us to skip those.
int secondGap = charLowerStart - charCapitalEnd; // similar to above, but between uppercase and lowercase letters.
// START generates a log to show us which characters we are considering for our UID.
NSMutableString *chars = [NSMutableString stringWithCapacity:amountOfChars];
for (int i = charNumStart; i <= charLowerEnd; i++) {
if ((i >= charNumStart && i <= charNumEnd) || (i >= charCapitalStart && i <= charCapitalEnd) || (i >= charLowerStart && i <= charLowerEnd)) {
[chars appendFormat:@"\n%c", (char) i];
}
}
NSLog(@"chars: %@", chars);
// END log
// Generate a uid of 20 characters that chooses from our desired range.
int uidLength = 20;
NSMutableString *uid = [NSMutableString stringWithCapacity:uidLength];
for (int i = 0; i < uidLength; i++) {
// Generate a random number within our character range.
int randomNum = arc4random() % amountOfChars;
// Add the lowest value number to line this up with a desirable character.
randomNum += charNumStart;
// if the number is in the letter range, skip over the characters between the numbers and letters.
if (randomNum > charNumEnd) {
randomNum += firstGap;
}
// if the number is in the lowercase letter range, skip over the characters between the uppercase and lowercase letters.
if (randomNum > charCapitalEnd) {
randomNum += secondGap;
}
// append the chosen character.
[uid appendFormat:@"%c", (char) randomNum];
}
NSLog(@"uid: %@", uid);
// Generate a UID that selects any kind of character, including a lot of punctuation. It's a bit easier to do it this way.
int amountOfAnyCharacters = charLowerEnd - charNumStart; // A new range of characters.
NSMutableString *multiCharUid = [NSMutableString stringWithCapacity:uidLength];
for (int i = 0; i < uidLength; i++) {
// Generate a random number within our new character range.
int randomNum = arc4random() % amountOfAnyCharacters;
// Add the lowest value number to line this up with our range of characters.
randomNum += charNumStart;
// append the chosen character.
[multiCharUid appendFormat:@"%c", (char) randomNum];
}
NSLog(@"multiCharUid: %@", multiCharUid);
在进行随机字符生成时,我更喜欢直接使用整数并将其转换,而不是编写我想要抽取的字符列表。在顶部声明变量使其更具系统独立性,但此代码假定数字的值低于字母,并且大写字母的值低于小写字母。
Swift的替代解决方案
func generateString(len: Int) -> String {
let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
let lettersLength = UInt32(countElements(letters))
let result = (0..<len).map { _ -> String in
let idx = Int(arc4random_uniform(lettersLength))
return String(letters[advance(letters.startIndex, idx)])
}
return "".join(result)
}
char
数组很好地解决了问题,完全没有必要用NSString
。事实上,使用[letters characterAtIndex:(rand() % [letters length])]
似乎比仅仅使用letters[rand() % strlen(letters)]
更加冗长。Foundation 类库确实很有帮助,但对于最简单的任务,它们可能会让我们的代码变得晦涩难懂而非使其更清晰易读。 - Jonathan SterlingcharacterAtIndex:
返回的是一个unichar
,所以你可能需要使用%C
而不是%c
。 - user102008arc4random_uniform((int)[letters length])
。 - knshn