【问题标题】:How to check if a string only contains alphanumeric characters in objective C?如何检查字符串是否仅包含目标C中的字母数字字符?
【发布时间】:2010-12-12 21:33:13
【问题描述】:

我正在处理一个小型 iphone 项目,我需要检查输入的用户名是否仅包含字母数字字符? (A-Z, a-z, 0-9。我将如何检查它?

【问题讨论】:

标签: iphone objective-c string alphanumeric


【解决方案1】:

您可以将this regular expression library 用于ObjectiveC。使用以下正则表达式进行匹配:

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

【讨论】:

  • 为什么过分了?这是最简单的解决方案,易于阅读,字符串验证是正则表达式的用途。
【解决方案2】:

如果您不想为此任务引入正则表达式库...

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

【讨论】:

  • 这只是顺便检查字符串两端的字符而不是整个字符串
  • developer.apple.com/library/mac/documentation/Cocoa/Reference/…:我引用:“返回一个新字符串,该字符串通过从给定字符集中包含的接收者字符的两个中删除”
  • 操作的问题是确保字符串包含个字母数字字符。我想这是一种间接的方式,可以肯定的是,它完成了我会给你的任务。不过,在我看来,stringByReplaceCharacterSet 更适合。
  • 这是对 CPU 周期和 RAM 的浪费,以防您担心。最好只扫描字符串,直到找到非字母数字字符。
  • 不正确。 NSCharacterSet.alphanumericCharacterSet 包含比 [a-zA-Z0-9] 更多的字符,例如,变音符号(如 é)和上标(如 ²)。 stackoverflow.com/questions/1671605/…
【解决方案3】:

这将起作用:

@implementation NSString (alphaOnly)

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

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

@end

【讨论】:

  • ? YES : NO 并不是必需的。逻辑比较的结果已经是一个布尔值。
  • 我知道,我只是喜欢看,以免以后再看,以为我漏掉了什么。
  • 虽然没有被发帖人标记为答案,但我更喜欢这个解决方案而不是标记为答案的解决方案。它非常有用,并且可以轻松扩展以针对其他字符集进行测试。竖起大拇指。
  • Albert,您可以放心,CoreFoundation 团队比这更聪明。
  • 不正确。 NSCharacterSet.alphanumericCharacterSet 包含比 [a-zA-Z0-9] 更多的字符,例如,变音符号(如 é)和上标(如 ²)。 stackoverflow.com/questions/1671605/…
【解决方案4】:

我真的很喜欢 RegexKit Lite 框架。它使用 ICU 正则表达式库,该库已包含在 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

【讨论】:

    【解决方案5】:

    基于NSCharacterSet 的答案没有给出您对日语等文本可能期望的结果,通常声称它们确实包含字母数字字符 - 正在执行的测试归结为“只有字母或数字”,而日语 (等)字符计为“字母”。

    如果您要检查拉丁字符与外语(例如日语),那么来自“How to determine if an NSString is latin based?”的答案可能会有所帮助:

    BOOL isLatin = [myString canBeConvertedToEncoding:NSISOLatin1StringEncoding];
    

    NSASCIIStringEncoding 也可以用来代替 NSISOLatin1StringEncoding 来进一步限制有效字符。您还可以在之后使用 NSCharacterSet 进行测试,以排除特殊字符,如 !、# 等。

    【讨论】:

    • 特殊字符如“#”、“@”等也可以转换为拉丁编码,因此此方法仅适用于拉丁与特定区域设置的检查。
    【解决方案6】:
    - (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 类中

    【讨论】:

    • 我觉得你可以把最后一段代码改成return r.location == NSNotFound;
    • 你的代码中不应该是r.location != NSNotFound吗?也就是说,如果在不需要的集合中找不到,则为字母数字。我认为你有这种倒置。
    【解决方案7】:

    我进行了一些相当广泛的性能测试,在选择如何验证您的字母数字字符串时需要考虑几个因素。首先,当然是你甚至可能不关心性能。如果您的应用程序很少验证字符串,或者甚至只验证一次,那么任何能够为您提供所需行为的方法都可以。除此之外,这是我的表现结果。

    对于自定义字符集(比如字母数字字符,没有 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 函数进行任何测试。

    【讨论】:

    • 很好的答案。 [NSCharacterSet alphanumericCharacterSet] 有很多小问题。简单而不优雅的“abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890”正是我在字母数字检测中避免中文/日文字符所需要的。
    【解决方案8】:

    您可以使用NSString 正则表达式功能,在iOS 3.2 中引入:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-16
      • 1970-01-01
      • 2014-06-21
      • 1970-01-01
      • 2012-06-12
      • 2020-12-12
      • 2015-01-04
      相关资源
      最近更新 更多