코코아에서 임의의 영숫자 문자열 생성


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
그냥 여기에 넣겠습니다. 간단한 배열이 제대로 작동 할 때 NSStringfor 를 사용할 이유가 없습니다 . 실제로, 사용하는 것이 나보다 간결하지 않은 것 같습니다 . Foundation 수업은 실제로 도움이되지만 가장 간단한 것은 코드를 향상시키는 대신 모호하게 만드는 것입니다. letterschar[letters characterAtIndex:(rand() % [letters length])]letters[rand() % strlen(letters)]
— Jonathan Sterling

3
%C%ccharacterAtIndex:unichar
— 21:01

8
arc4random을 사용하면 배열 길이가 2의 거듭 제곱이 아닌 경우 바이어스 된 결과가 생성됩니다. arc4random_uniform이이를 수정합니다.
— jlukanta

9
오, 컴파일러는 정밀도를 잃는 것에 대한 경고를하므로 int로 캐스팅하는 것이 좋습니다.arc4random_uniform((int)[letters length])
— knshn

103

정확히 당신이 묻는 것은 아니지만 여전히 유용합니다.

[[NSProcessInfo processInfo] globallyUniqueString]

샘플 출력 :

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

2
이것이 문제를 해결하는 가장 짧고 가장 간단한 방법입니다.
— adib

하이픈이 있어도 문제가되지 않는다면 굉장합니다!
— fatuhoku

마일로 최고의 답변
— Rambatino

"코코아로 임의의 영숫자 문자열을 생성"할 필요가 있습니다. YAGNI가 "길이를 통과"해야한다는 요구 사항을 추가했기 때문에 OP가 요구하는 것만은 아닙니다!
— jkoreska

5
이것은 대부분의 사용에는 문제가 없지만 보안을 위해 임의의 문자열이 필요한 경우 사용하지 마십시오. 고유! = 랜덤. 길이는 일정하고 사용되는 문자 범위가 제한됩니다 (0-9, AF,-= 17, aZ의 경우 62 대 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
각각 10 문자의 1M 암호를 생성하여 테스트했으며 훌륭하게 작동합니다.
— NaXir 2016 년

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 2016 년

5
이것으로 아무 문제가 없습니다. 훌륭하고 간결한 솔루션입니다. (SO가
— 다운 보트

최고의 솔루션. 유일한 의견은 정적 방법으로 만들 것입니다.
— Andrei Tchijov

9
유일한 단점은 실제로 영숫자가 아니라 소문자라는 것입니다. ;-)
— PrimaryFeather

나는 당신이 25에서 26으로 변경해야한다고 생각합니다. 그렇지 않으면 결코 'z'를 얻지 못할 것입니다.
— Marcus Adams

28

16 진수 문자로만 자신을 제한하려는 경우 가장 간단한 옵션은 UUID를 생성하는 것입니다.

NSString *uuid = [NSUUID UUID].UUIDString;

출력 예 : 16E3DF0B-87B3-4162-A1A1-E03DB2F59654.

더 작은 임의의 문자열을 원하면 처음 8 자만 잡을 수 있습니다.

버전 4 UUID는 3 번째 및 4 번째 그룹의 첫 번째 문자가 무작위가 아님을 의미합니다 (항상 , 또는 , 4중 하나임 ).89AB

문자열의 다른 모든 문자는 완전히 임의적이며 동일한 UUID가 두 번 생성 될 위험없이 수백 년 동안 매초마다 수백만 개의 UUID를 생성 할 수 있습니다.


1
간단하게 사용할 수 있습니다NSString *uuid = [UUID UUID]
— orkoden

@ orkoden 덕분에 내 코드는 일부 iOS 5 코드에서 나왔습니다. 최신 iOS 6 / OS X 10.8 API를 사용하도록 답변을 업데이트하겠습니다.
— Abhi Beckert 14

@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 (count (alphabet))로 대체했다
— scootermg

확인. 나는 하드 코딩 64된을 계산 된 것으로 교체했습니다 upperBound. 나는 upperBound그것이 더 나은 것으로 생각하기 때문에 블록 외부에서 계산 합니다.
— ma11hew28

'alphabet.characters.count'를 사용하여 '(String)'유형의 인수 목록으로 'count'를 호출 할 수 없음
— Zaporozhchenko Oleksandr

알파벳 반환 [alphabet.startIndex.advancedBy (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

스위프트의 대체 솔루션

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

임의의 유니 코드 문자열을 원하는 경우 임의의 바이트를 만든 다음 유효한 바이트를 사용할 수 있습니다.

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

유효한 UTF-8 문자열을 얻으려면 NSString에서 NSData로 또는 그 반대로 변환해야합니다. 길이는 반드시 끝에 생성 된 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

스위프트 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.