Tạo một chuỗi ký tự chữ và số ngẫu nhiên trong Ca cao


145

Tôi muốn gọi một phương thức, truyền cho nó độ dài và để nó tạo ra một chuỗi ký tự chữ và số ngẫu nhiên.

Có thư viện tiện ích nào ngoài kia có thể có một loạt các loại chức năng này không?

Câu trả lời:


312

Đây là một thực hiện nhanh chóng và bẩn. Chưa được thử nghiệm.

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;
}

1
genRandStringLpm chỉ nên trả về RandomString. Không có lý do để phân bổ và init (và không phải autorelease!) Một chuỗi hoàn toàn mới.
kevingessner

5
Chỉ cần đặt nó ra khỏi đó. Không có lý do để sử dụng một NSStringđể letterskhi một đơn giản charmảng sẽ chỉ làm việc tốt. Trong thực tế, việc sử dụng [letters characterAtIndex:(rand() % [letters length])]dường như đối với tôi là ít súc tích hơn chỉ letters[rand() % strlen(letters)]. Các lớp Foundation thực sự hữu ích, nhưng đối với những điều đơn giản nhất, chúng có thể phục vụ để làm xáo trộn mã của chúng tôi hơn là tăng cường nó.
Jonathan Sterling

3
bạn có thể muốn %Cthay vì %c, vì characterAtIndex:trả về mộtunichar
user102008

8
Sử dụng arc4random sẽ tạo ra kết quả sai lệch khi độ dài mảng không phải là lũy thừa của hai. arc4random_uniform sửa lỗi này.
jlukanta

9
oh trình biên dịch sẽ đưa ra một cảnh báo về việc mất độ chính xác, vì vậy tốt hơn là chuyển sang intarc4random_uniform((int)[letters length])
knshn

103

Không chính xác những gì bạn yêu cầu, nhưng vẫn hữu ích:

[[NSProcessInfo processInfo] globallyUniqueString]

Đầu ra mẫu:

450FEA63-2286-4B49-8ACC-9822C7D4356B-1376-00000239A4AC4FD5

2
Đây là cách ngắn nhất và đơn giản nhất để giải quyết câu hỏi.
adib

Ngay cả khi nó có dấu gạch nối trong đó - nếu đó không phải là một mối quan tâm thì thật tuyệt vời!
fatuhoku 23/1/2015

Câu trả lời hay nhất bằng một dặm
Rambatino 9/2/2015

Hoàn hảo cho nhu cầu của tôi để "tạo ra một chuỗi ký tự chữ và số ngẫu nhiên trong ca cao". Không chính xác những gì OP yêu cầu chỉ bởi vì anh ta thêm yêu cầu "vượt qua chiều dài" mà YAGNI!
jkoreska

5
Điều này có thể ổn đối với hầu hết các mục đích sử dụng nhưng KHÔNG SỬ DỤNG nếu bạn cần một chuỗi ngẫu nhiên cho mục đích bảo mật. Độc đáo! = Ngẫu nhiên. Độ dài không đổi, phạm vi các ký tự được sử dụng bị giới hạn (0-9, AF, - = 17, so với 62 đối với aZ. 0-9). Chuỗi này là duy nhất nhưng có thể dự đoán.
amcc

67
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];
}

13
Bạn có thực sự cần phải truy vấn độ dài của alphabetmỗi lần? Nó là hằng số và không phụ thuộc vào vòng lặp.
jv42

1
Được kiểm tra bằng cách tạo mật khẩu 1M mỗi ký tự 10 ký tự và nó hoạt động rất tốt.
NaXir

1
NSArraylưu trữ nó length, không nên là một nút cổ chai hiệu suất.
Pascal

Tôi đồng ý. Đó là một truy cập tài sản đơn giản. Nó không được tính mỗi lần bạn hỏi.
devios1

45

Chắc chắn bạn có thể làm điều này ngắn hơn:

+(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;
}

2
Tại sao là -1? Không có gì sai với điều này cả. Nó giống như nhỏ nhất được tối ưu hóa nhất trong số tất cả các câu trả lời.
John Riselvato

5
Không có gì sai với cái này. Đó là một giải pháp tốt đẹp và súc tích. (Tôi ước SO sẽ thi hành một bình luận về downvote.)
alvi

Giải pháp tốt nhất. Nhận xét duy nhất, tôi sẽ làm cho nó phương thức tĩnh.
Andrei Tchijov

9
Nhược điểm duy nhất là nó không thực sự là chữ và số, mà chỉ là chữ thường. ;-)
Sơ cấp

Tôi nghĩ bạn cần thay đổi từ 25 thành 26, nếu không bạn sẽ không bao giờ nhận được 'z'.
Marcus Adams

28

Nếu bạn sẵn sàng giới hạn bản thân chỉ ở các ký tự hex, thì tùy chọn đơn giản nhất là tạo UUID:

NSString *uuid = [NSUUID UUID].UUIDString;

Ví dụ đầu ra : 16E3DF0B-87B3-4162-A1A1-E03DB2F59654.

Nếu bạn muốn một chuỗi ngẫu nhiên nhỏ hơn thì bạn chỉ có thể lấy 8 ký tự đầu tiên.

Đó là một UUID phiên bản 4 có nghĩa là nhân vật đầu tiên trong 3 và 4 nhóm không phải là ngẫu nhiên (họ sẽ luôn luôn được 4và một trong những 8, 9, Ahoặc B).

Mỗi ký tự khác trong chuỗi là hoàn toàn ngẫu nhiên và bạn có thể tạo ra hàng triệu UUID mỗi giây trong hàng trăm năm mà không có nhiều rủi ro về cùng một UUID được tạo hai lần.


1
Bạn chỉ có thể sử dụngNSString *uuid = [UUID UUID]
orkoden

@orkoden cảm ơn, mã của tôi là từ một số mã iOS 5. Tôi sẽ cập nhật câu trả lời của mình để sử dụng API iOS 6 / OS X 10.8 mới hơn.
Abhi Beckert

@AbhiBeckert có an toàn khi chỉ sử dụng 8 ký tự đầu tiên mà không có nguy cơ nhận được 8 ký tự đầu tiên không?
Vishal Singh

1
@VishalSingh vâng, nó an toàn, mặc dù rõ ràng bạn càng làm cho nó ngắn thì nguy cơ va chạm càng cao.
Abhi Beckert

3
NSString * uuid = [UUID UUID] .UUIDString; sẽ cung cấp cho bạn lỗi "Sử dụng UUID định danh không khai báo", do đó, chỉ cần một thay đổi nhỏ trong mã sử dụng NSString * uuid = [NSUUID UUID] .UUIDString;
Abbas Mulani

24

Một phiên bản thể loại của câu trả lời của Jeff B.

NSString + Ngẫu nhiên.h

#import <Foundation/Foundation.h>

@interface NSString (Random)

+ (NSString *)randomAlphanumericStringWithLength:(NSInteger)length;

@end

NSString + Ngẫu nhiên

#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

1
Đây là một ví dụ tuyệt vời về cách sử dụng Danh mục!
ElmerCat

7

Bạn cũng có thể tạo UUID. Mặc dù không thực sự ngẫu nhiên, chúng rất phức tạp và độc đáo khiến chúng có vẻ ngẫu nhiên cho hầu hết các mục đích sử dụng. Tạo một chuỗi dưới dạng một chuỗi và sau đó lấy một phạm vi các ký tự bằng với độ dài được truyền.


Tôi sẽ khuyên mạnh mẽ chống lại điều này cho bất cứ điều gì liên quan đến an ninh. Giả ngẫu nhiên là một trong những tin tặc lớn nhất mà các hacker sử dụng trong các hệ thống thâm nhập, bởi vì chúng cung cấp khả năng dự đoán. Sử dụng càng gần với ngẫu nhiên càng tốt.
Shayne

5

Nhanh

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)))]
    })
}

1
Ngắn & ngọt ngào. Làm việc cho tôi ngoại trừ khi tôi thay đổi bảng chữ cái, nó bị lỗi vì chiều dài bảng chữ cái được mã hóa cứng. Tôi đã thay thế 64 bằng UInt32 (đếm (bảng chữ cái))
scootermg

ĐỒNG Ý. Tôi đã thay thế mã hóa cứng 64bằng một máy tính upperBound. Tôi tính toán upperBoundbên ngoài khối vì tôi nghĩ rằng nó hoạt động tốt hơn.
ma11hew28

Không thể gọi 'đếm' với danh sách đối số loại '(Chuỗi)' bằng cách sử dụng '
Zaporozhchenko Oleksandr

trả về bảng chữ cái [alph.startIndex.advifiedBy (Int (arc4random_uniform (UpperBound)))
Zaporozhchenko Oleksandr

4

Đây là một cách khác nhau để giải quyết nó. Thay vì sử dụng một chuỗi ký tự đã chuẩn bị, bạn có thể chuyển giữa các số nguyên và ký tự và tạo một danh sách các ký tự động để chọn. Nó khá gọn gàng và nhanh, nhưng có thêm một chút mã.

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);

Khi tôi thực hiện việc tạo nhân vật ngẫu nhiên, tôi thích làm việc trực tiếp với các số nguyên và bỏ qua chúng, thay vì viết ra danh sách các ký tự mà tôi muốn rút ra. Khai báo các biến ở trên cùng làm cho nó độc lập hơn với hệ thống, nhưng mã này giả định rằng các số sẽ có giá trị thấp hơn các chữ cái và các chữ cái viết hoa sẽ có giá trị thấp hơn các chữ cái viết thường.


3

Giải pháp thay thế trong 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)
}

2

Thêm vào câu trả lời hay được đưa ra bởi Melvin, đây là một hàm tôi đã thực hiện ( trong SWIFT! ) Để có được một chuỗi ngẫu nhiên:

func randomStringOfLength(length:Int)->String{
    var wantedCharacters:NSString="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXZY0123456789"
    var s=NSMutableString(capacity: length)
    for (var i:Int = 0; i < length; i++) {
        let r:UInt32 = arc4random() % UInt32( wantedCharacters.length)
        let c:UniChar = wantedCharacters.characterAtIndex( Int(r) )
        s.appendFormat("%C", c)
    }
    return s
}

Đây là kết quả kiểm tra từ cuộc gọi randomStringOfLength(10): uXa0igA8wm


2

Tạo chuỗi ngẫu nhiên chữ và số viết thường với độ dài cho trước:

-(NSString*)randomStringWithLength:(NSUInteger)length
{
    NSMutableString* random = [NSMutableString stringWithCapacity:length];

    for (NSUInteger i=0; i<length; i++)
    {
        char c = '0' + (unichar)arc4random()%36;
        if(c > '9') c += ('a'-'9'-1);
        [random appendFormat:@"%c", c];
    }

    return random;
}

2

Sửa đổi một vài ý tưởng ở đây và thực hiện Swift 4.0

extension String
{
    subscript (i: Int) -> Character
    {
        return self[index(startIndex, offsetBy:i)]
    }

    static func Random(length:Int=32, alphabet:String="ABCDEF0123456789") -> String
    {
        let upperBound = UInt32(alphabet.count)
        return String((0..<length).map { _ -> Character in
            return alphabet[Int(arc4random_uniform(upperBound))]
        })
    }
}

Sử dụng:

let myHexString = String.Random()
let myLongHexString = String.Random(length:64)
let myLettersString = String.Random(length:32, alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZ")

1

Nếu bạn muốn một chuỗi unicode ngẫu nhiên, bạn có thể tạo các byte ngẫu nhiên và sau đó sử dụng các chuỗi hợp lệ.

    OSStatus sanityCheck = noErr;
    uint8_t * randomBytes = NULL;
    size_t length = 200; // can of course be variable

    randomBytes = malloc( length * sizeof(uint8_t) );
    memset((void *)randomBytes, 0x0, length);

    sanityCheck = SecRandomCopyBytes(kSecRandomDefault, length, randomBytes);

    if (sanityCheck != noErr) NSLog(@"Error generating random bytes, OSStatus == %ld.", sanityCheck);

    NSData* randomData = [[NSData alloc] initWithBytes:(const void *)randomBytes length: length];
    if (randomBytes) free(randomBytes);

    NSString* dataString = [[NSString alloc] initWithCharacters:[randomData bytes] length:[randomData length]];  // create an NSString from the random bytes
    NSData* tempData = [dataString dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];             // remove illegal characters from string
    NSString* randomString = [[NSString alloc] initWithData:tempData encoding:NSUTF8StringEncoding];

Việc chuyển đổi từ NSString sang NSData trở lại là cần thiết để có được chuỗi UTF-8 hợp lệ. Xin lưu ý rằng độ dài sẽ không nhất thiết là độ dài của NSString được tạo cuối cùng.


1

Tôi đã làm điều này bằng cách sử dụng một đơn giản char[]thay vì một NSString *bảng chữ cái. Tôi đã thêm nó vào danh mục NSString.

static const char __alphabet[] =
    "0123456789"
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "abcdefghijklmnopqrstuvwxyz";
+ (NSString *)randomString:(int)length
{
    NSMutableString *randomString = [NSMutableString stringWithCapacity:length];
    u_int32_t alphabetLength = (u_int32_t)strlen(__alphabet);
    for (int i = 0; i < length; i++) {
        [randomString appendFormat:@"%c", __alphabet[arc4random_uniform(alphabetLength)]];
    }
    return randomString;
}

1
static NSUInteger length = 32;
static NSString *letters = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
NSMutableString * randomString = [NSMutableString stringWithCapacity:length];
for (NSInteger i = 0; i < length; ++i) {
    [randomString appendFormat: @"%C", [letters characterAtIndex:(NSUInteger)arc4random_uniform((u_int32_t)[letters length])]];
}

1

Phương thức gọi:


NSString *string = [self stringWithRandomSuffixForFile:@"file.pdf" withLength:4]

Phương pháp:


- (NSString *)stringWithRandomSuffixForFile:(NSString *)file withLength:(int)length
{
    NSString *alphabet = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    NSString *fileExtension = [file pathExtension];
    NSString *fileName = [file stringByDeletingPathExtension];
    NSMutableString *randomString = [NSMutableString stringWithFormat:@"%@_", fileName];

    for (int x = 0; x < length; x++) {
        [randomString appendFormat:@"%C", [alphabet characterAtIndex: arc4random_uniform((int)[alphabet length]) % [alphabet length]]];
    }
    [randomString appendFormat:@".%@", fileExtension];

    NSLog(@"## randomString: %@ ##", randomString);
    return randomString;
}

Các kết quả:


## randomString: file_Msci.pdf ##
## randomString: file_xshG.pdf ##
## randomString: file_abAD.pdf ##
## randomString: file_HVwV.pdf ##

1

cho Swift 3.0

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
}

0
#define ASCII_START_NUMERS 0x30
#define ASCII_END_NUMERS 0x39
#define ASCII_START_LETTERS_A 0x41
#define ASCII_END_LETTERS_Z 0x5A
#define ASCII_START_LETTERS_a 0x61
#define ASCII_END_LETTERS_z 0x5A

-(NSString *)getRandomString:(int)length {
    NSMutableString *result = [[NSMutableString alloc]init];
    while (result.length != length) {
        NSMutableData* data = [NSMutableData dataWithLength:1];
        SecRandomCopyBytes(kSecRandomDefault, 1, [data mutableBytes]);
        Byte currentChar = 0;
        [data getBytes:&currentChar length:1];
        NSString *s = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        if (currentChar > ASCII_START_NUMERS && currentChar < ASCII_END_NUMERS) { // 0 to 0
            [result appendString:s];
            continue;
        }
        if (currentChar > ASCII_START_LETTERS_A && currentChar < ASCII_END_LETTERS_Z) { // 0 to 0
            [result appendString:s];
            continue;
        }
        if (currentChar > ASCII_START_LETTERS_a && currentChar < ASCII_END_LETTERS_z) { // 0 to 0
            [result appendString:s];
            continue;
        }
    }
    return result;
}

0

Sửa đổi cho câu trả lời của keithyip:

+ (NSString *)randomAlphanumericStringWithLength:(NSInteger)length
{
    static NSString * const letters = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        srand(time(NULL));
    });

    NSMutableString *randomString = [NSMutableString stringWithCapacity:length];

    for (int i = 0; i < length; i++) {
        [randomString appendFormat:@"%C", [letters characterAtIndex:arc4random() % [letters length]]];
    }

    return randomString;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.