zoukankan      html  css  js  c++  java
  • 字符串处理(正则表达式、NSScanner扫描、CoreParse解析器)-b

    搜索

    在一个字符串中搜索子字符串

    • 最灵活的方法

    1
    - (NSRange)rangeOfString:(NSString *)aString options:(NSStringCompareOptions)mask range:(NSRange)searchRange locale:(NSLocale *)locale

    格式化字符串

    • 3个方法

    1
    2
    3
    -initWithFormat:
    -initWithFormat:arguments:
    +stringWithFormat:

    整数

    • 可以同时工作在32位和64位的

    1
    2
    3
    uint64_t p = 2305843009213693951;
    NSString *s = [NSString stringWithFormat:@"The ninth Mersenne prime is %llu", (unsigned long long) p];
    // "The ninth Mersenne prime is 2305843009213693951"
    Modifierd, io, u, x, X
    hh signed char unsigned char
    h short unsigned short
    (none) int unsigned int
    l(ell) long unsigned long
    j intmax_t uintmax_t
    t ptrdiff_t  
    z   size_t
    • 转换规则

    1
    2
    3
    4
    5
    int m = -150004021;
    uint n = 150004021U;
    NSString *s = [NSString stringWithFormat:@"d:%d i:%i o:%o u:%u x:%x X:%X", m, m, n, n, n, n];
    // "d:-150004021 i:-150004021 o:1074160465 u:150004021 x:8f0e135 X:8F0E135"
    //o是八进制
    • 设置最小字段宽度和最小数字位数

    1
    2
    3
    4
    5
    6
    int m = 42;
    NSString *s = [NSString stringWithFormat:@"'%4d' '%-4d' '%+4d' '%4.3d' '%04d'", m, m, m, m, m];
    // "[ 42] [42 ] [ +42] [ 042] [0042]"
    m = -42;
    NSString *s = [NSString stringWithFormat:@"'%4d' '%-4d' '%+4d' '%4.3d' '%04d'", m, m, m, m, m];
    // "[ -42] [-42 ] [ -42] [-042] [-042]"
    • %p可打印指针,和%#x不同的是它可以同时在32位和64位执行

    浮点数

    • 使用%f和%g

    1
    2
    3
    4
    5
    double v[5] = {12345, 12, 0.12, 0.12345678901234, 0.0000012345678901234};
    NSString *s = [NSString stringWithFormat:@"%g %g %g %g %g", v[0], v[1], v[2], v[3], v[4]];
    // "12345 12 0.12 0.123457 1.23457e-06"
    NSString *s = [NSString stringWithFormat:@"%f %f %f %f %f", v[0], v[1], v[2], v[3], v[4]];
    // "12345.000000 12.000000 0.120000 0.123457 0.000001"

    多行文字

    • 使用 来

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    NSString *limerick = @"A lively young damsel named Menzies
    "
    @"Inquired: «Do you know what this thenzies?»
    "
    @"Her aunt, with a gasp,
    "
    @"Replied: "It's a wasp,
    "
    @"And you're holding the end where the stenzies.
    ";
    • 等价写法

    1
    2
    3
    4
    5
    6
    NSString *limerick = @"A lively young damsel named Menzies
    Inquired: «Do you know what this thenzies?»
    Her aunt, with a gasp,
    Replied: "It's a wasp,
    And you're holding the end where the stenzies.
    ";

    更简洁的方法

    1
    NSString * string = @"The man " @"who knows everything " @"learns nothing" @".";

    替换字符串

    • NSMutableString的四个方法

    1
    2
    3
    4
    -deleteCharactersInRange:
    -insertString:atIndex:
    -replaceCharactersInRange:withString:
    -replaceOccurrencesOfString:withString:options:range:

    NSString的方法

    1
    2
    3
    -stringByReplacingOccurrencesOfString:withString:
    -stringByReplacingOccurrencesOfString:withString:options:range:
    -stringByReplacingCharactersInRange:withString:

    NSMutableString不会创建新字符串,性能会好点

    1
    2
    3
    4
    5
    6
    7
    NSMutableString *string; // 假设我们已经有了一个名为 string 的字符串
    // 现在要去掉它的一个前缀,做法如下:
    NSString *prefix = @"WeDon’tWantThisPrefix"
    NSRange r = [string rangeOfString:prefix options:NSAnchoredSearch range:NSMakeRange(0, string.length) locale:nil];
    if (r.location != NSNotFound) {
         [string deleteCharactersInRange:r];
    }

    连接字符串

    1
    2
    NSArray *names = @["Hildr", @"Heidrun", @"Gerd", @"Guðrún", @"Freya", @"Nanna", @"Siv", @"Skaði", @"Gróa"];
    NSString *result = [names componentsJoinedByString:@", "];

    字符串解析

    正则表达式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    NSError *error = nil;
    NSString *pattern = @"(w+) = #(p{Hex_Digit}{6})";
    NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:pattern
    options:0
    error:&error];
    NSTextCheckingResult *result = [expression firstMatchInString:string
    options:0
    range:NSMakeRange(0, string.length)];
    NSString *key = [string substringWithRange:[result rangeAtIndex:1]];
    NSString *value = [string substringWithRange:[result rangeAtIndex:2]];

    将字符串分解成数组,使用componentsSeparatedByString:这个方法,或者 enumerateSubstringsInRange:options:usingBlock:。如果是按照行来进行分解可以使用option这个参数 传NSStringEnumerationByLines

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    NSString *input = @“
    backgroundColor = #ff0000
    textColor = #0000ff
    "
    NSString *pattern = @"(w+) = #([da-f]{6})";
    NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:pattern
    options:0
    error:NULL];
    NSArray *lines = [input componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
    NSMutableDictionary *result = [NSMutableDictionary dictionary];
    for (NSString *line in lines) {
         NSTextCheckingResult *textCheckingResult = [expression firstMatchInString:line
              options:0
              range:NSMakeRange(0, line.length)];
         NSString* key = [line substringWithRange:[textCheckingResult rangeAtIndex:1]];
         NSString* value = [line substringWithRange:[textCheckingResult rangeAtIndex:2]];
         result[key] = value;
    }
    return result;

    扫描

    • NSScanner

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    NSScanner *scanner = [NSScanner scannerWithString:string];
    //默认情况下,扫描器会跳过所有空格符和换行符。但这里我们只希望跳过空格符
    scanner.charactersToBeSkipped = [NSCharacterSet whitespaceCharacterSet];
    //定义一个十六进制字符集
    NSCharacterSet *hexadecimalCharacterSet =
    [NSCharacterSet characterSetWithCharactersInString:@"0123456789abcdefABCDEF"];
     
    NSMutableDictionary *result = [NSMutableDictionary dictionary];
    while (!scanner.isAtEnd) {
         NSString *key = nil;
         NSString *value = nil;
         NSCharacterSet *letters = [NSCharacterSet letterCharacterSet];
         BOOL didScan = [scanner scanCharactersFromSet:letters intoString:&key] &&
              [scanner scanString:@"=" intoString:NULL] &&
              [scanner scanString:@"#" intoString:NULL] &&
              [scanner scanCharactersFromSet:hexadecimalCharacterSet intoString:&value] &&
         value.length == 6;
         result[key] = value;
         [scanner scanCharactersFromSet:[NSCharacterSet newlineCharacterSet]
              intoString:NULL]; // 继续扫描下一行
    }
    return result;

    解析器

    • 设计一个能够用(100,0,255)或者#ff0000这样的字符来定义颜色的方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    - (NSDictionary *)parse:(NSString *)string error:(NSError **)error
    {
         self.scanner = [NSScanner scannerWithString:string];
         self.scanner.charactersToBeSkipped = [NSCharacterSet whitespaceCharacterSet];
     
         NSMutableDictionary *result = [NSMutableDictionary dictionary];
         NSCharacterSet *letters = [NSCharacterSet letterCharacterSet]
         while (!self.scanner.isAtEnd) {
              NSString *key = nil;
              UIColor *value = nil;
              BOOL didScan = [self.scanner scanCharactersFromSet:letters intoString:&key] &&
                   [self.scanner scanString:@"=" intoString:NULL] &&
                   [self scanColor:&value];
              result[key] = value;
              [self.scanner scanCharactersFromSet:[NSCharacterSet newlineCharacterSet]
                   intoString:NULL]; // 继续扫描下一行
         }
    }
     
    - (BOOL)scanColor:(UIColor **)out
    {
         return [self scanHexColorIntoColor:out] || [self scanTupleColorIntoColor:out];
    }
     
    //扫描设置#ff0000这样的
    - (BOOL)scanHexColorIntoColor:(UIColor **)out
    {
         NSCharacterSet *hexadecimalCharacterSet =
              [NSCharacterSet characterSetWithCharactersInString:@"0123456789abcdefABCDEF"];
         NSString *colorString = NULL;
         if ([self.scanner scanString:@"#" intoString:NULL] &&
              [self.scanner scanCharactersFromSet:hexadecimalCharacterSet
              intoString:&colorString] &&
              colorString.length == 6) {
              *out = [UIColor colorWithHexString:colorString];
              return YES;
         }
         return NO;
    }
     
    - (BOOL)scanTupleColorIntoColor:(UIColor **)out
    {
         NSInteger red, green, blue = 0;
         BOOL didScan = [self.scanner scanString:@"(" intoString:NULL] &&
              [self.scanner scanInteger:&red] &&
              [self.scanner scanString:@"," intoString:NULL] &&
              [self.scanner scanInteger:&green] &&
              [self.scanner scanString:@"," intoString:NULL] &&
              [self.scanner scanInteger:&blue] &&
              [self.scanner scanString:@")" intoString:NULL];
         if (didScan) {
              *out = [UIColor colorWithRed:(CGFloat)red/255.
                   green:(CGFloat)green/255.
                   blue:(CGFloat)blue/255.
                   alpha:1];
              return YES;
         else {
              return NO;
         }
    }

    符号化处理

    先进星扫描,使用NSScanner来解析这个表达式

    1
    2
    myView.left = otherView.right * 2 + 10
    viewController.view.centerX + myConstant <= self.view.centerX
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    NSScanner *scanner = [NSScanner scannerWithString:contents];
    NSMutableArray *tokens = [NSMutableArray array];
    while (![scanner isAtEnd]) {
         for (NSString *operator in @[@"=", @"+", @"*", @">=", @"<=", @"."]) {
              if ([scanner scanString:operator intoString:NULL]) {
                   [tokens addObject:operator];
              }
         }
    }
    //接下来识别非符号的只包含字母的string
    NSString *result = nil;
    if ([scanner scanCharactersFromSet:[NSCharacterSet letterCharacterSet]
              intoString:&result]) {
         [tokens addObject:result];
    }
     
    //NSScanner有scanDouble:来扫描double
    double doubleResult = 0;
    if ([scanner scanDouble:&doubleResult]) {
         [tokens addObject:@(doubleResult)];
    }
    //完成后用将需要解析的表达式放入试试
    NSString* example = @"myConstant = 100
    "
         @"
    myView.left = otherView.right * 2 + 10
    "
         @"viewController.view.centerX + myConstant <= self.view.centerX";
    NSArray *result = [self.scanner tokenize:example];
    NSArray *expected = @[@"myConstant", @"=", @100, @"myView", @".", @"left",
         @"=", @"otherView", @".", @"right", @"*", @2, @"+",
         @10, @"viewController", @".", @"view", @".",
         @"centerX", @"+", @"myConstant", @"<=", @"self",
         @".", @"view", @".", @"centerX"];
    XCTAssertEqualObjects(result, expected);

    进行语法解析,需要语法分析库描述我们的语言。下面代码就是为那个布局约束语言写的解析语法,用的扩展的巴科斯范式EBNF写法:

    1
    2
    3
    4
    5
    6
    7
    8
    constraint = expression comparator expression
    comparator = "=" ">=" "<="
    expression = keyPath "." attribute addMultiplier addConstant
    keyPath = identifier | identifier "." keyPath
    attribute = "left" "right" "top" "bottom" "leading" "trailing" "width" "height" "centerX" "centerY" "baseline"
    addMultiplier = "*" atom
    addConstant = "+" atom
    atom = number | identifier

    还有很多Objective-C的语法解析,更多的可以在CocoaPods上找到:http://cocoapods.org/?q=parse。比较好的就是CoreParse,地址:https://github.com/beelsebob/CoreParse,但是需要使用它支持的语法。下面就是CoreParse支持的格式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    NSString* grammarString = [@[
         @"Atom ::= num@'Number' | ident@'Identifier';",
         @"Constant ::= name@'Identifier' '=' value@<Atom>;",
         @"Relation ::= '=' | '>=' | '<=';",
         @"Attribute ::= 'left' | 'right' | 'top' | 'bottom' | 'leading' | 'trailing' | 'width' | 'height' | 'centerX' | 'centerY' | 'baseline';",
         @"Multiplier ::= '*' num@'Number';",
         @"AddConstant ::= '+' num@'Number';",
         @"KeypathAndAttribute ::= 'Identifier' '.' <AttributeOrRest>;",
         @"AttributeOrRest ::= att@<Attribute> | 'Identifier' '.' <AttributeOrRest>;",
         @"Expression ::= <KeypathAndAttribute> <Multiplier>? <AddConstant>?;",
         @"LayoutConstraint ::= lhs@<Expression> rel@<Relation> rhs@<Expression>;",
         @"Rule ::= <Atom> | <LayoutConstraint>;",
    ] componentsJoinedByString:@"
    "];

    一个规则匹配后解析器就找到同样名称的类

    1
    2
    3
    4
    5
    6
    7
    - (id)parser:(CPParser *)parser didProduceSyntaxTree:(CPSyntaxTree *)syntaxTree
         NSString *ruleName = syntaxTree.rule.name;
         if ([ruleName isEqualToString:@"Attribute"]) {
              return self.layoutAttributes[[[syntaxTree childAtIndex:0] keyword]];
         }
    ...
    }

    完整的解析器代码在:https://github.com/objcio/issue-9-string-parsing。里面有个解析类可以用来解析复杂的布局约束,如下:

    1
    viewController.view.centerX + 20 <= self.view.centerX * 0.5

    可以得到如下结果,方便转换成NSLayoutConstraint对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    (<Expression: self.keyPath=(viewController, view),
         self.attribute=9,
         self.multiplier=1,
         self.constant=20>
    -1
    <Expression: self.keyPath=(self, view),
         self.attribute=9,
         self.multiplier=0.5,
         self.constant=0>)

    字符串的渲染

    UILabel

    • label默认显示一行,如果设置numberOfLines为大于1的话可以显示指定行数,如果设置为0,则多少行都显示

    • attributedText属性可以显示富文本

    • label的font,textColor,textAlignment,shadowColor和shadowOffset属性可以改变外观。

    • 改变程序内所有Label的风格,可以使用[UILabel appearance]方法

    UITextField

    • text field只限于单行

    • UITextfield实现了UITextInputTraits协议,这个协议需要指定键盘外观和操作等细节。比如显示什么键盘和返回按键响应等

    • 可以通过设置左右辅助视图,或者设置背景来自定义输入框风格了。

    UITextView

    TableView中显示动态文本

    Table view的Delegate有个方法用来计算高度:tableView:heightForRowAtIndexPath:。自定义一个UITableViewCell的子类

    1
    2
    3
    4
    5
    6
    7
    - (void)layoutSubviews
    {
         [super layoutSubviews];
         self.textLabel.frame = CGRectInset(self.bounds,
              MyTableViewCellInset,
              MyTableViewCellInset);
    }

    计算真实高度需要使用boundingRectWithSize:options:context: 这个方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
         CGFloat labelWidth = self.tableView.bounds.size.width - MyTableViewCellInset*2;
         NSAttributedString *text = [self attributedBodyTextAtIndexPath:indexPath];
         NSStringDrawingOptions options = NSStringDrawingUsesLineFragmentOrigin |
              NSStringDrawingUsesFontLeading;
         CGRect boundingRect = [text boundingRectWithSize:CGSizeMake(labelWidth, CGFLOAT_MAX)
              options:options
              context:nil];
     
         return (CGFloat) (ceil(boundingRect.size.height) + MyTableViewCellInset*2);
    }

    使用Text Kit和NSAttributedString进行布局

    先设置attributes

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    CGFloat const fontSize = 15;
     
    NSMutableDictionary *body1stAttributes = [NSMutableDictionary dictionary];
    body1stAttributes[NSFontAttributeName] = [UIFont fontWithName:@"BodoniSvtyTwoITCTT-Book"
    size:fontSize];
    NSMutableParagraphStyle *body1stParagraph = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
    body1stParagraph.alignment = NSTextAlignmentJustified;
    body1stParagraph.minimumLineHeight = fontSize + 3;
    body1stParagraph.maximumLineHeight = body1stParagraph.minimumLineHeight;
    body1stParagraph.hyphenationFactor = 0.97;
    body1stAttributes[NSParagraphStyleAttributeName] = body1stParag
    raph;

    这里字体为BodoniSvtyTwoITCTT,如果需要查看更多字体可以使用 +[UIFont familyNames]这个方法。为了得到字体的名字,可以使用 +[UIFont fontNamesForFamilyName:]。接下来创建段落的属性

    1
    2
    3
    4
    5
    NSMutableDictionary *bodyAttributes = [body1stAttributes mutableCopy];
    NSMutableParagraphStyle *bodyParagraph =
         [bodyAttributes[NSParagraphStyleAttributeName] mutableCopy];
    bodyParagraph.firstLineHeadIndent = fontSize;
    bodyAttributes[NSParagraphStyleAttributeName] = bodyParagraph;

    装饰段落风格,使用装饰字体将文本居中对齐,装饰字符的前后加上空白段落

    1
    2
    3
    4
    5
    6
    7
    8
    NSMutableDictionary *ornamentAttributes = [NSMutableDictionary dictionary];
    ornamentAttributes[NSFontAttributeName] = [UIFont fontWithName:@"BodoniOrnamentsITCTT"
         size:36];
    NSMutableParagraphStyle *ornamentParagraph = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
    ornamentParagraph.alignment = NSTextAlignmentCenter;
    ornamentParagraph.paragraphSpacingBefore = fontSize;
    ornamentParagraph.paragraphSpacing = fontSize;
    ornamentAttributes[NSParagraphStyleAttributeName] = ornamentParagraph;

    显示数字表格table,表格布局示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    NSCharacterSet *decimalTerminator = [NSCharacterSet
         characterSetWithCharactersInString:decimalFormatter.decimalSeparator];
    NSTextTab *decimalTab = [[NSTextTab alloc]
         initWithTextAlignment:NSTextAlignmentCenter
         location:100
         options:@{NSTabColumnTerminatorsAttributeName:decimalTerminator}];
    NSTextTab *percentTab = [[NSTextTab alloc] initWithTextAlignment:NSTextAlignmentRight
         location:200
         options:nil];
    NSMutableParagraphStyle *tableParagraphStyle =
         [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
    tableParagraphStyle.tabStops = @[decimalTab, percentTab];

    显示列表的属性设置如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    NSMutableDictionary *listAttributes = [bodyAttributes mutableCopy];
    NSMutableParagraphStyle *listParagraph =
         [listAttributes[NSParagraphStyleAttributeName] mutableCopy];
    listParagraph.headIndent = fontSize * 3;
    listParagraph.firstLineHeadIndent = fontSize;
    NSTextTab *listTab = [[NSTextTab alloc] initWithTextAlignment:NSTextAlignmentNatural
         location:fontSize * 3
         options:nil];
    listParagraph.tabStops = @[listTab];
    listAttributes[NSParagraphStyleAttributeName] = listParagraph;

    字符串本地化

    原文:http://www.starming.com/index.php?v=index&view=63  感谢分享

  • 相关阅读:
    【乱侃】How do they look them ?
    【softeware】Messy code,some bug of Youdao notebook in EN win7
    【随谈】designing the login page of our project
    【web】Ad in security code, making good use of resource
    SQL数据库内存设置篇
    关系数据库的查询优化策略
    利用SQL未公开的存储过程实现分页
    sql语句总结
    sql中使用cmd命令注销登录用户
    SQLServer 分页存储过程
  • 原文地址:https://www.cnblogs.com/isItOk/p/5419394.html
Copyright © 2011-2022 走看看