web-dev-qa-db-ja.com

目的Cの文字列に英数字のみが含まれているかどうかを確認する方法は?

私は小さなiphoneプロジェクトに取り組んでいますが、入力したuserNameに英数字のみが含まれているかどうかを確認する必要がありますか? (A-Z, a-z, 0-9。確認するにはどうすればよいですか?

47
Cheng Lai

この1つのタスクのために正規表現ライブラリを持ち込みたくない場合...

NSString *str = @"aA09";
NSCharacterSet *alphaSet = [NSCharacterSet alphanumericCharacterSet];
BOOL valid = [[str stringByTrimmingCharactersInSet:alphaSet] isEqualToString:@""]; 
86
Jason Harwig

これは動作します:

@implementation NSString (alphaOnly)

- (BOOL) isAlphaNumeric
{
    NSCharacterSet *unwantedCharacters = 
       [[NSCharacterSet alphanumericCharacterSet] invertedSet];

    return ([self rangeOfCharacterFromSet:unwantedCharacters].location == NSNotFound);
}

@end
61
NSResponder

NSCharacterSetベースの回答では、日本語などのテキストに期待する結果が得られず、しばしば英数字が含まれていると主張されます。実行されるテストは、「文字または数字のみ」と日本語(など)文字は「文字」としてカウントされます。

ラテン文字と外国語(日本語など)をチェックしようとしている場合、「 NSStringがラテン語ベースかどうかを判断する方法? 」からの回答が役立つ場合があります。

BOOL isLatin = [myString canBeConvertedToEncoding:NSISOLatin1StringEncoding];

NSISOLatin1StringEncodingの代わりにNSASCIIStringEncodingを使用して、有効な文字をさらに制限することもできます。 NSCharacterSetを後でテストして、!、#などの特殊文字を除外することもできます。

8
JosephH

かなり広範なパフォーマンステストを実行しましたが、英数字の文字列を検証する方法を選択する際に考慮すべき考慮事項がいくつかあります。最初に、もちろん、パフォーマンスを気にかけないこともあります。アプリが文字列を検証することはめったにないか、1回しか検証しない場合は、必要な動作を提供する方法であれば問題ありません。それを超えて、ここに私のパフォーマンス結果があります。

カスタム文字セット(たとえば、Unicode文字やマークのない英数字)の場合、これは最初の実行で最も高速です。

NSCharacterSet *alphanumericSet = [NSCharacterSet characterSetWithCharactersInString:@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"];
NSString *result = [self stringByTrimmingCharactersInSet:alphanumericSet];

return [result isEqualToString:@""];

[NSCharacterSet alphanumericCharacterSet]のような事前に計算された文字セットを使用しても問題ない場合、これは最速でした:

NSCharacterSet *alphanumericSet = [NSCharacterSet alphanumericCharacterSet];
alphanumericSet = alphanumericSet.invertedSet;
NSRange range = [self rangeOfCharacterFromSet:alphanumericSet];

return (range.location == NSNotFound);

これらの検証を繰り返し実行する場合、dispatch_onceを使用して静的変数の文字セットをキャッシュすると非常に役立ちます。その場合、最初のコンパイル時間を吸収できると確信している場合、正規表現を使用すると、実際にカスタム文字セットで最速になります:

static NSRegularExpression *alphanumericRegex;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    alphanumericRegex = [NSRegularExpression regularExpressionWithPattern:@"^[a-zA-Z0-9]*$" options:NSRegularExpressionCaseInsensitive error:nil];
});
NSUInteger numberOfMatches = [alphanumericRegex numberOfMatchesInString:self options:0 range:NSMakeRange(0, self.length)];

return (numberOfMatches == 1);

正規表現を使用したくない場合、キャッシュされたrangeOfCharacterFromSetのカスタムセットバージョンは、キャッシュされたstringByTrimmingCharactersInCharacterSet:メソッドよりも優先されます。

static NSCharacterSet *alphanumericSet;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    alphanumericSet = [NSCharacterSet characterSetWithCharactersInString:@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"];
    alphanumericSet = alphanumericSet.invertedSet;
});

NSRange range = [self rangeOfCharacterFromSet:alphanumericSet];

return (range.location == NSNotFound);

事前計算済みセットの場合、キャッシュされたrangeOfCharacterFromSet:メソッドが再び最速でした:

static NSCharacterSet *alphanumericSet;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    alphanumericSet = [NSCharacterSet alphanumericCharacterSet];
    alphanumericSet = alphanumericSet.invertedSet;
});

NSRange range = [self rangeOfCharacterFromSet:alphanumericSet];

return (range.location == NSNotFound);

そして、みんなの情報にとって、isSupersetOfSet:メソッドは、キャッシュされているかどうかにかかわらず、最も低速でした。 isSupersetOfSet:はかなり遅いようです。

NSCharacterSet *stringSet = [NSCharacterSet characterSetWithCharactersInString:self];
NSCharacterSet *alphanumericSet = [NSCharacterSet alphanumericCharacterSet];

return [alphanumericSet isSupersetOfSet:stringSet];

基になるCFCharacterSet関数のテストは行いませんでした。

5
Jon Shier
- (BOOL)isAlphaNumeric
{
     NSCharacterSet *s = [NSCharacterSet characterSetWithCharactersInString:@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'. "];
     s = [s invertedSet];
     NSRange r = [self rangeOfCharacterFromSet:s];
     if (r.location == NSNotFound) {
         return NO;
     } else {
       return YES;
    }
}

空白などの新しい文字を追加/削除する柔軟性があります

P.Sこのメソッドは、NSStringカテゴリでコピー/貼り付けできます

3
Abhinav Singh

RegexKitLiteフレームワークが本当に好きです。 ICU regexライブラリを使用します。これはOSXに既に含まれており、Unicodeセーフです。

NSString *str = @"testString";
[str isMatchedByRegex:@"^[a-zA-Z0-9]*$"]; // strict ASCII-match
[str isMatchedByRegex:@"^[\p{L}\p{N}]*$"]; // unicode letters and numbers match
2
Adrian

IOS 3.2で導入されたNSString正規表現機能を使用できます。

- (BOOL)isAlphanumeric:(NSString *)string {
    return [string rangeOfString:@"^[a-zA-Z0-9]+$" options:NSRegularExpressionSearch].location != NSNotFound;
}
0
Rob