สร้างสตริงตัวอักษรผสมตัวเลขแบบสุ่มในโกโก้


145

ฉันต้องการที่จะเรียกวิธีการผ่านความยาวและมีมันสร้างสตริงตัวอักษรและตัวเลขแบบสุ่ม

มียูทิลิตี้ไลบรารีใดบ้างที่อาจมีฟังก์ชั่นประเภทนี้มากมาย

คำตอบ:


312

นี่คือการใช้งานที่รวดเร็วและสกปรก ยังไม่ได้ทดสอบ

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
genRandStringLength ควรคืนค่า randomString ไม่มีเหตุผลที่จะจัดสรรและเริ่มต้น (และไม่เลิกอัตโนมัติ!) สตริงใหม่ทั้งหมด
kevingessner

5
เพิ่งจะเอามันออกไป ไม่มีเหตุผลที่จะใช้NSStringสำหรับlettersเมื่อcharอาเรย์ง่ายๆจะทำงานได้ดี ในความเป็นจริงโดยใช้ดูเหมือนว่าฉันจะกระชับน้อยกว่าเพียงแค่[letters characterAtIndex:(rand() % [letters length])] letters[rand() % strlen(letters)]ชั้นเรียนของมูลนิธินั้นมีประโยชน์จริง ๆ แต่สำหรับสิ่งที่ง่ายที่สุดพวกเขาสามารถให้บริการเพื่อทำให้รหัสของเราชัดเจนยิ่งขึ้นแทนที่จะปรับปรุงให้ดีขึ้น
Jonathan Sterling

3
คุณอาจต้องการ%Cแทน%cเพราะcharacterAtIndex:ส่งคืน aunichar
user102008

8
การใช้ arc4random จะสร้างผลลัพธ์แบบเอนเอียงเมื่อความยาวของอาเรย์ไม่ใช่พลังของทั้งสอง arc4random_uniform แก้ไขสิ่งนี้
jlukanta

9
โอ้คอมไพเลอร์จะให้คำเตือนสำหรับการสูญเสียความแม่นยำดังนั้นดีกว่าที่จะส่งไปยัง intarc4random_uniform((int)[letters length])
knshn

103

ไม่ใช่สิ่งที่คุณถาม แต่ก็ยังมีประโยชน์:

[[NSProcessInfo processInfo] globallyUniqueString]

ตัวอย่างผลลัพธ์:

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

2
นี่เป็นวิธีที่สั้นและตรงไปตรงมาที่สุดในการตอบคำถาม
adib

แม้ว่ามันจะมียัติภังค์อยู่ในนั้น - หากนั่นไม่ใช่ข้อกังวลก็ยอดเยี่ยม!
fatuhoku

คำตอบที่ดีที่สุดโดยไมล์
Rambatino

สมบูรณ์แบบสำหรับความต้องการของฉัน "สร้างสตริงตัวอักษรและตัวเลขแบบสุ่มในโกโก้" ไม่ใช่สิ่งที่ OP ขอเพียงเพราะเขาเพิ่มข้อกำหนดในการ "ส่งต่อความยาว" ซึ่ง YAGNI!
jkoreska

5
สิ่งนี้อาจใช้ได้สำหรับการใช้งานส่วนใหญ่ แต่ห้ามใช้หากคุณต้องการสตริงแบบสุ่มเพื่อความปลอดภัย ไม่ซ้ำ! = สุ่ม ความยาวเป็นค่าคงที่ช่วงของอักขระที่ใช้มี จำกัด (0-9, AF, - = 17, vs 62 สำหรับ aZ. 0-9) สตริงนี้ไม่ซ้ำกัน แต่คาดการณ์ได้
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
คุณต้องการสอบถามความยาวของalphabetแต่ละครั้งจริง ๆ หรือไม่ เป็นค่าคงที่และไม่ขึ้นอยู่กับลูป
jv42

1
ทดสอบโดยการสร้างรหัสผ่าน 1M 10 ตัวอักษรและใช้งานได้ดี
NaXir

1
NSArrayแคชlengthไม่ควรเป็นคอขวดของประสิทธิภาพ
ปาสกาล

ฉันเห็นด้วย. มันเป็นคุณสมบัติที่เข้าถึงได้ง่าย มันไม่นับตัวเองทุกครั้งที่คุณถาม
devios1

45

แน่นอนคุณสามารถทำให้สั้นกว่านี้:

+(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
ทำไม -1 ไม่มีอะไรผิดปกติกับเรื่องนี้เลย มันเหมือนคำตอบที่เล็กที่สุดในทุกคำตอบ
John Riselvato

5
ไม่มีอะไรผิดปกติกับอันนี้ มันเป็นทางออกที่ดีและรัดกุม (ฉันต้องการเช่นนั้นจะบังคับใช้ความคิดเห็นใน downvotes.)
Alvi

ทางออกที่ดีที่สุด ความคิดเห็นเท่านั้นฉันจะทำให้วิธีการคงที่
Andrei Tchijov

9
ข้อเสียอย่างเดียวคือมันไม่ใช่ตัวอักษรและตัวเลข แต่เป็นตัวอักษรตัวเล็ก ;-)
PrimaryFeather

ฉันคิดว่าคุณต้องเปลี่ยน 25 เป็น 26 มิฉะนั้นคุณจะไม่ได้รับ 'z'
Marcus Adams

28

หากคุณยินดีที่จะ จำกัด ตัวคุณให้เป็นอักขระฐานสิบหกเท่านั้นตัวเลือกที่ง่ายที่สุดคือสร้าง UUID:

NSString *uuid = [NSUUID UUID].UUIDString;

ตัวอย่างผลลัพธ์: 16E3DF0B-87B3-4162-A1A1-E03DB2F59654.

หากคุณต้องการสตริงสุ่มที่มีขนาดเล็กลงคุณสามารถคว้าได้เพียง 8 อักขระแรก

เป็น UUID รุ่น 4 ซึ่งหมายความว่าอักขระตัวแรกในกลุ่มที่ 3 และ 4 ไม่ได้สุ่ม (พวกเขาจะเป็น4หนึ่งใน8นั้น9เสมอAหรือB)

อักขระอื่น ๆ ในสตริงนั้นสุ่มอย่างสมบูรณ์และคุณสามารถสร้าง UUID หลายล้านตัวทุก ๆ วินาทีเป็นเวลาหลายร้อยปีโดยไม่มีความเสี่ยงมากที่ UUID เดียวกันจะถูกสร้างขึ้นสองครั้ง


1
คุณสามารถใช้NSString *uuid = [UUID UUID]
orkoden

@orkoden ขอบคุณรหัสของฉันมาจากรหัส iOS 5 ฉันจะอัปเดตคำตอบเพื่อใช้ iOS 6 / OS X 10.8 API ที่ใหม่กว่า
Abhi Beckert

@AbhiBeckert มีความปลอดภัยในการใช้งานเพียง 8 ตัวอักษรแรกโดยไม่เสี่ยงต่อการได้รับ 8 ตัวแรกหรือไม่
Vishal Singh

1
@VishalSingh ใช่มันปลอดภัยแม้จะเห็นได้ชัดว่ายิ่งคุณสั้นก็ยิ่งทำให้ความเสี่ยงในการชนสูงขึ้น
Abhi Beckert

3
NSString * uuid = [UUID UUID] .UUIDString; จะให้ข้อผิดพลาด "การใช้ UUID ตัวระบุที่ไม่ได้ประกาศ" ดังนั้นการเปลี่ยนแปลงเพียงเล็กน้อยในการใช้รหัส NSString * uuid = [NSUUID UUID] .UUIDString;
Abbas Mulani

24

หมวดหมู่คำตอบของ Jeff 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

1
นี่เป็นตัวอย่างที่ดีของวิธีใช้หมวดหมู่!
ElmerCat

7

คุณสามารถสร้าง UUID ได้เช่นกัน ในขณะที่ไม่สุ่มอย่างแท้จริงพวกเขามีความซับซ้อนและไม่ซ้ำกันซึ่งทำให้พวกเขาปรากฏแบบสุ่มสำหรับการใช้งานส่วนใหญ่ สร้างหนึ่งรายการเป็นสตริงจากนั้นใช้ช่วงของอักขระเท่ากับความยาวที่ส่งผ่าน


ฉันขอแนะนำอย่างยิ่งยวดต่อสิ่งนี้เกี่ยวกับความปลอดภัย หลอกแบบสุ่มเป็นหนึ่งในแฮกเกอร์ช่องโหว่ที่ใหญ่ที่สุดที่ใช้ในระบบการเจาะเพราะพวกเขาให้การคาดการณ์ ใช้ใกล้เคียงกับการสุ่มจริงเท่าที่จะทำได้
Shayne

5

รวดเร็ว

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
สั้นและหวาน ทำงานให้ฉันยกเว้นเมื่อฉันเปลี่ยนตัวอักษรมันล้มเหลวเพราะความยาวของตัวอักษรนั้นเป็นรหัสยาก ฉันแทนที่ 64 ด้วย UInt32 (นับ (ตัวอักษร))
scootermg

ตกลง. ฉันแทนที่ hardcoded กับการคำนวณ64 upperBoundฉันคำนวณupperBoundนอกบล็อกเพราะฉันคิดว่ามันทำงานได้ดีขึ้น
ma11hew28

ไม่สามารถเรียกใช้ 'count' พร้อมกับรายการอาร์กิวเมนต์ของประเภท '(String)' ที่จับได้โดยใช้ 'alphabet.characters.count'
Zaporozhchenko Oleksandr

return ตัวอักษร [ตัวอักษร. เริ่มต้น. ขั้นสูงโดย (Int (arc4random_uniform (UpperBound))))
Zaporozhchenko Oleksandr

4

นี่เป็นวิธีที่แตกต่างกันในการจัดการมัน แทนที่จะใช้สตริงอักขระที่เตรียมไว้คุณสามารถแปลงระหว่างจำนวนเต็มและอักขระและสร้างรายการอักขระแบบไดนามิกเพื่อเลือก มันค่อนข้างลีนและรวดเร็ว แต่มีรหัสอีกเล็กน้อย

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

เมื่อฉันสร้างตัวละครแบบสุ่มฉันชอบที่จะทำงานโดยตรงกับจำนวนเต็มและใช้มันแทนที่จะเขียนรายการตัวอักษรที่ฉันต้องการดึงออกมา การประกาศตัวแปรที่ด้านบนทำให้ระบบเป็นอิสระมากขึ้น แต่รหัสนี้อนุมานว่าตัวเลขจะมีค่าต่ำกว่าตัวอักษรและตัวอักษรตัวพิมพ์ใหญ่นั้นจะมีค่าต่ำกว่าตัวอักษรตัวเล็ก


3

โซลูชันทางเลือกใน 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

การเพิ่มคำตอบที่ดีที่ Melvin มอบให้นี่คือฟังก์ชันที่ฉันทำ ( ใน SWIFT! ) เพื่อรับสตริงแบบสุ่ม:

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
}

นี่คือผลการทดสอบจากการโทรrandomStringOfLength(10): uXa0igA8wm


2

สร้างสตริงสุ่มตัวอักษรผสมตัวเลขและตัวอักษรที่มีความยาวที่กำหนด:

-(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

การปรับเปลี่ยนแนวคิดเล็กน้อยที่นี่และใน 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))]
        })
    }
}

การใช้งาน:

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

1

หากคุณต้องการสตริง unicode แบบสุ่มคุณสามารถสร้างไบต์แบบสุ่มจากนั้นใช้สตริงที่ถูกต้อง

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

การแปลงจาก NSString เป็น NSData และย้อนกลับเป็นสิ่งจำเป็นในการรับสตริง UTF-8 ที่ถูกต้อง ระวังความยาวไม่จำเป็นต้องเป็นความยาวของ NSString ที่สร้างขึ้นในตอนท้าย


1

ฉันทำสิ่งนี้โดยใช้แบบง่ายchar[]แทนที่จะNSString *ใช้ตัวอักษร ฉันเพิ่มสิ่งนี้ลงในหมวดหมู่ 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

วิธีการโทร:


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

วิธี:


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

ผล:


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

1

สำหรับ 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

การปรับเปลี่ยนสำหรับคำตอบของ 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;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.