2009-11-04 33 views
44

Tôi đang làm việc trên một dự án iphone nhỏ và tôi sẽ cần phải kiểm tra xem userName đã nhập chỉ chứa các ký tự chữ và số không? (A-Z, a-z, 0-9. Làm thế nào tôi sẽ đi về kiểm tra nó?Làm cách nào để kiểm tra xem chuỗi có chứa các ký tự chữ và số trong mục tiêu C không?

+0

Trong Swift: http://stackoverflow.com/questions/35992800/check-if-a-string-is-alphanumeric- trong swift – ma11hew28

Trả lời

83

Nếu bạn không muốn để mang lại trong một thư viện regex cho một nhiệm vụ này ...

NSString *str = @"aA09"; 
NSCharacterSet *alphaSet = [NSCharacterSet alphanumericCharacterSet]; 
BOOL valid = [[str stringByTrimmingCharactersInSet:alphaSet] isEqualToString:@""]; 
+0

thz alot dude tôi đã suy nghĩ một cái gì đó dọc theo cùng một dòng như bạn, nhưng chỉ không thể tìm ra cách –

+4

Điều này chỉ kiểm tra các ký tự trên cả hai đầu của chuỗi bằng cách này chứ không phải toàn bộ chuỗi – ragamufin

+0

không hoạt động cho tôi – NightFury

9

Bạn có thể sử dụng this regular expression library cho ObjectiveC. Sử dụng regex sau để phù hợp:

^[a-zA-Z0-9]*$ 
+2

Không sai, nhưng thực sự quá mức cần thiết. – Chuck

+1

Tại sao nó quá mức cần thiết? Đó là giải pháp đơn giản nhất, dễ đọc và xác nhận chuỗi là những gì regex được dự định. – Soviut

60

này sẽ làm việc:

@implementation NSString (alphaOnly) 

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

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

@end 
+11

'? CÓ: NO' không thực sự cần thiết. Kết quả của một so sánh lôgic đã là một giá trị boolean. – Chuck

+1

Tôi biết, tôi chỉ muốn nhìn thấy nó để tôi không đọc nó sau này và nghĩ rằng tôi để lại một cái gì đó. – NSResponder

+0

hey đó là tốt đẹp quá người đàn ông tôi không biết u có thể đảo ngược bộ ký tự. lol tự hỏi làm thế nào mà làm việc cho các ngôn ngữ khác như Trung Quốc –

2

Tôi thực sự thích khung ảnh RegexKitLite. Nó sử dụng thư viện regex ICU, đã được bao gồm trong OSX và an toàn unicode.

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

Các NSCharacterSet câu trả lời dựa trên không đưa ra kết quả mà bạn có thể mong đợi cho văn bản tiếng Nhật vv, thường tuyên bố rằng họ làm chứa các ký tự chữ và số - bài kiểm tra được thực hiện sôi xuống 'là chỉ có chữ hoặc số, và Các ký tự tiếng Nhật (vv) được tính là 'Chữ'. (. Ví dụ như Nhật Bản)

Nếu bạn đang cố gắng để kiểm tra các ký tự Latinh vs một ngôn ngữ nước ngoài, thì câu trả lời từ "How to determine if an NSString is latin based?" có thể giúp:

BOOL isLatin = [myString canBeConvertedToEncoding:NSISOLatin1StringEncoding]; 

NSASCIIStringEncoding cũng có thể được sử dụng thay cho NSISOLatin1StringEncoding để tiếp tục hạn chế các ký tự hợp lệ. Bạn cũng có thể kiểm tra bằng NSCharacterSet sau đó, để loại trừ ký tự đặc biệt như!, #, Vv

+0

Ký tự đặc biệt như '#', ' @ ', v.v. cũng có thể được chuyển đổi sang mã hóa latin, vì vậy phương pháp này chỉ hoạt động đối với séc séc so với ngôn ngữ latin. –

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

Có sự linh hoạt để thêm/bớt nhân vật mới như khoảng trắng

PS Phương pháp này có thể copy/paste trong Danh mục NSString

+3

Tôi nghĩ bạn có thể thay đổi đoạn mã cuối cùng thành 'return r.location == NSNotFound;' – agmezr

5

Tôi đã chạy một số thử nghiệm hiệu suất khá rộng và có một số cân nhắc cần tính đến khi chọn cách xác thực chuỗi ký tự chữ và số của bạn. Đầu tiên, tất nhiên, là bạn thậm chí có thể không quan tâm đến hiệu suất. Nếu ứng dụng của bạn hiếm khi xác nhận chuỗi, hoặc thậm chí chỉ có thể thực hiện một lần, bất kỳ phương thức nào cung cấp cho bạn hành vi bạn muốn là tốt. Ngoài ra, đây là kết quả hiệu suất của tôi.

Đối với các bộ ký tự tùy chỉnh (nói ký tự chữ, mà không ký tự Unicode hoặc dấu), đây là nhanh nhất cho một chạy ban đầu:

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

return [result isEqualToString:@""]; 

Nếu bạn đang okay sử dụng một nhân vật precomputed thiết như [NSCharacterSet alphanumericCharacterSet] thì đây là nhanh nhất:

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

return (range.location == NSNotFound); 

Caching bộ ký tự trong một biến tĩnh nhờ sủ dụng dispatch_once có thể giúp khá một chút nếu bạn chạy các kiểm chứng thực nhiều lần.Trong trường hợp đó, nếu bạn chắc chắn bạn có thể hấp thụ thời gian biên dịch ban đầu, sử dụng một regex thực sự hóa ra là nhanh nhất cho các bộ ký tự tùy chỉnh:

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

Nếu bạn không muốn sử dụng regex, phiên bản bộ tùy chỉnh của cache rangeOfCharacterFromSet cạnh ra các cache stringByTrimmingCharactersInCharacterSet: phương pháp:

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

Đối với bộ precomputed, các cache rangeOfCharacterFromSet: phương pháp đã một lần nữa nhanh nhất:

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

Và đối với thông tin của mọi người, phương pháp isSupersetOfSet: là chậm nhất, dù được lưu trong bộ nhớ cache hay không. Có vẻ như isSupersetOfSet: khá chậm.

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

return [alphanumericSet isSupersetOfSet:stringSet]; 

Tôi không thực hiện bất kỳ thử nghiệm nào về các hàm CFCharacterSet cơ bản.

+0

Câu trả lời hay. Rất nhiều gotchas nhỏ với [NSCharacterSet alphanumericCharacterSet]. "AbcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" đơn giản và không phù hợp là chính xác những gì tôi cần để tránh các ký tự Trung Quốc/Nhật Bản trong việc phát hiện chữ và số. – JeremyDay

0

Bạn có thể sử dụng NSString khả năng biểu thức chính quy, được giới thiệu trong iOS 3.2:

- (BOOL)isAlphanumeric:(NSString *)string { 
    return [string rangeOfString:@"^[a-zA-Z0-9]+$" options:NSRegularExpressionSearch].location != NSNotFound; 
} 
Các vấn đề liên quan