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


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.