zoukankan      html  css  js  c++  java
  • Objective-C:Foundation框架-常用类-NSString全解

      Foundation框架中常用的类有字符串、集合、字典等,这里介绍字符串NSString。本文分别介绍了NSString的创建、从文件里读取NSString字符串、通过函数改变外部的NSString变量的值、NSString字符串的导出、NSString的常用方法等5个部分。

    1.NSString的创建:

    #pragma mark NSString的创建
    void stringCreate() {
        // char *s = "A String!"; // C语言中的字符串
        
        // 这种方式创建出来的字符串是不需要释放的
        NSString *str1 = @"A String!";
        
        NSString *str2 = [[NSString alloc] init];
        str2 = @"A String!";
        [str2 release];
        
        NSString *str3 = [[NSString alloc] initWithString:@"A String!"];
        [str3 release];
        // 不需要管理内存
        str3 = [NSString stringWithString:@"A String!"];
        
        NSString *str4 = [[NSString alloc] initWithUTF8String:"A String!"];
        [str4 release];
        str4 = [NSString stringWithUTF8String:"A String!"];
        
        NSString *str5 = [[NSString alloc] initWithFormat:@"My age is %i and height is %.2f", 19, 1.55f];//(图1)
        
        // 这句代码放在中间会造成2个错误:
        // 1.前面创建的字符串没有被释放
        // 2.后面创建的字符串会释放过度,造成野指针错误
        // str5 = [NSString stringWithFormat:@"My age is %i and height is %.2f", 19, 1.55f];//(图2、3)
        
        NSLog(@"str5:%@", str5);
        [str5 release];
        
        str5 = [NSString stringWithFormat:@"My age is %i and height is %.2f", 19, 1.55f];
    }

             

                          

                                   (图1)                                                        (图2)                                                           (图3)

      野指针的产生:通过“[[NSString alloc] initWithFormat:@"My age is %i and height is %.2f", 19, 1.55f];”(动态创建)这句创建的对象是需要手动释放内存的,如果在还没有手动释放之前又通过静态方法“str5 = [NSString stringWithFormat:@"My age is %i and height is %.2f", 19, 1.55f];”(静态创建)给str5对象赋值,那么str5将指向新的一块内存,而原来的那块内存没有对象指向它了,但是也没有被释放,就成了野指针。动态方式创建一般都有对应的静态方法创建。

    2.从文件里读取NSString字符串

    void stringCreate2() {
        // 从文件中读取文本
        NSString *path = @"/Users/apple/Desktop/test.txt";
        // 这个方法已经过期,不能解析中文
        // NSString *str1 = [NSString stringWithContentsOfFile:path];
        
        // 定义一个NSError变量
        NSError *error;
        // 指定字符串编码为UTF-8: NSUTF8StringEncoding
        NSString *str1 = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
        //最后的一个参数不能传error,一定要传error的地址,它是指向error这个指针的指针
        if (error == nil) { // 没有错误信息
            NSLog(@"读取文件成功:%@", str1);
        } else {
            NSLog(@"读取文件失败:%@", error);
        }
        
        NSURL *url = [NSURL URLWithString:@"file:///Users/apple/Desktop/test.txt"];
        NSString *str2 = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
        NSLog(@"%@", str2);
        
        NSURL *url2 = [NSURL URLWithString:@"http://www.baidu.com"];
        NSString *str3 = [NSString stringWithContentsOfURL:url2 encoding:NSUTF8StringEncoding error:nil];
        NSLog(@"%@", str3);
    }

    3.通过函数改变外部的NSString变量的值

    先看一种情况:

    void test(NSString *str){
    str = @"123";
    }
    
    int main(int argc, const char *argv[])
    {
        autoreleasepool{
            NSString *s = @"456";
            test(s);
            NSLog(@"%@", s);
        }
        return 0;
    }

      运行结果为:456。s的值并没有改变,分析如下:

      指针变量s起初指向456(图1),当调用test函数时,传入参数s,函数会开辟一块存储空间存储指针变量str,指针变量是存储地址的,参数s将其存储的地址赋值给str(值传递)(图2),因此str存储的地址也指向了456这个对象,“str = @"123";”执行后,系统又开辟了一块存储空间存储123,接着让str指向这个对象(图3)。而s的值根本没有变,它一直都指向456。所以,对于一个函数,如果只是把一个指针传进去,外面的值是不会变的。

                                 (图1)                                                         (图2)                                                                 (图3)  

      若要通过函数改变外面指针指向的值,需要用到指针的指针,也就是把外面指针的地址传进去。

    void test(NSString **str) {
        *str = @"123";
        // s = @"123";
    }
    int main(int argc, const char *argv[])
    {
        autoreleasepool{
            NSString *s = @"456";
            test(&s);
            NSLog(@"%@", s);
        }
        return 0;
    }

      指针变量是这样的,那对于一般类型的变量呢?看下面的例子:

    void test2(int p){
        p = 9;
    }
    
    int main(int argc, const char * argv[])
    {
    
        @autoreleasepool {
            int a = 10;
            test2(a);
            NSLog(@"%i", a);
        }
        return 0;
    }

      运行结果:10;

    void test2(int *p) {
       *p = 9;
    }
    
    int main(int argc, const char * argv[])
    {
    
        @autoreleasepool {
            int a = 10;
            test2(&a);
            NSLog(@"%i", a);
        }
        return 0;
    }

      运行结果:9。

      效果是一样的。再次说明,如果要设计一个方法,改变外面传进来的参数,那应该将外面这个参数的地址传递给函数。

    4.NSString字符串的导出

    #pragma mark 字符串的导出
    void stringExport() {
        NSString *str = @"123456我是字符串!!!!";
        // 如果文件不存在,会自动创建文件
        // 如果文件夹不存在,会直接报错
        NSString *path = @"/Users/apple/Desktop/abc.txt";
        
        NSError *error;
        // 编码指定错误也会报错
        // YES代表要进行原子性操作,也就是会创建一个中间的临时文件
        [str writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:&error];
        if (error) {
            // [error localizedDescription]会返回主要的错误信息
            NSLog(@"写入失败:%@", [error localizedDescription]);
        } else {
            NSLog(@"写入成功");
        }
    }

    原子性与非原子性的区别:

      若写入文件为原子性操作,则在写入内容之前会创建一个临时文件,先将内容写入临时文件,待内容完好无损地写入临时文件后,再将临时文件里的内容移到目标文件中,中途如果出错,临时文件出问题,不会影响到目标文件;非原子性操作直接将内容写入目标文件,一旦中途出错,可能造成目标文件里只有部分内容传入的情况。

    5.NSString的常用方法

      1 #pragma mark 字符串的大小写处理
      2 void caseTest() {
      3     NSString *str = @"GuangDong";
      4     // 转成大写
      5     NSLog(@"大写:%@", [str uppercaseString]);
      6     // 转成小写
      7     NSLog(@"小写:%@", [str lowercaseString]);
      8     // 首字母变大写,其他字母变小写
      9     NSLog(@"首字母变大写:%@", [@"aGE" capitalizedString]);
     10 }
     11 
     12 #pragma mark 字符串的比较
     13 void compare() {
     14     // 检测字符串的内容是否相同
     15     BOOL result = [@"abc" isEqualToString:@"abc"];
     16     NSLog(@"%i", result);
     17     
     18     // NSOrderedAscending  右边的字符串比左边大
     19     // NSOrderedSame  两个字符串的内容相同
     20     // NSOrderedDescending  左边的字符串比右边的大
     21     NSComparisonResult result2 = [@"abc" compare:@"Abc"];
     22     if (result2 == NSOrderedSame) {
     23         NSLog(@"两个字符串的内容相同");
     24     } else if (result2 == NSOrderedAscending) {
     25         NSLog(@"右边 > 左边");
     26     } else if (result2 == NSOrderedDescending) {
     27         NSLog(@"右边 < 左边");
     28     }
     29 }
     30 
     31 #pragma mark 字符串的搜索
     32 void search() {
     33     NSString *str = @"123456456.txt";
     34     
     35     NSLog(@"是否以22开头:%i", [str hasPrefix:@"22"]);
     36     NSLog(@"是否以txt结尾:%i", [str hasSuffix:@"txt"]);
     37     
     38     // 搜索字符串
     39     NSRange range = [str rangeOfString:@"456"];
     40     // range.length == 0
     41     if (range.location == NSNotFound) {
     42         NSLog(@"不能找到");
     43     } else {
     44         NSLog(@"找到的范围是:%@", NSStringFromRange(range));
     45     }
     46     
     47     // 从尾部开始搜索字符串
     48     range = [str rangeOfString:@"456" options:NSBackwardsSearch];
     49     NSLog(@"%@", NSStringFromRange(range));
     50     
     51     // 指定范围进行搜索
     52     // [str rangeOfString:@"456" options:NSBackwardsSearch range:<#(NSRange)#>];
     53 }
     54 
     55 #pragma mark 字符串的截取
     56 void subString() {
     57     NSString *str = @"123456";
     58     
     59     // 从索引3开始截取到尾部(包括3)
     60     NSLog(@"%@", [str substringFromIndex:3]);
     61     
     62     // 从头部开始截取到索引3之前(不包括3)
     63     NSLog(@"%@", [str substringToIndex:3]);
     64     
     65     // 指定范围进行截取
     66     NSRange range = NSMakeRange(2, 3);
     67     NSLog(@"%@", [str substringWithRange:range]);
     68     
     69     NSString *str2 = @"a-b-c-d-5";
     70     NSArray *array = [str2 componentsSeparatedByString:@"-"];
     71     NSLog(@"%@", array);
     72     
     73     NSString *str3 =  [array objectAtIndex:0];
     74     NSLog(@"%@", str3);
     75 }
     76 
     77 #pragma mark 与路径相关
     78 void pathTest() {
     79     // 快速创建一个自动释放的数组
     80     NSMutableArray *components = [NSMutableArray array];
     81     [components addObject:@"Users"];
     82     [components addObject:@"MJ"];
     83     [components addObject:@"Desktop"];
     84     // 将数组中的所有字符串拼接成一个路径
     85     NSString *path = [NSString pathWithComponents:components];
     86     NSLog(@"%@", path);
     87     
     88     // 将路径分解成一个数组
     89     NSArray *cmps = [path pathComponents];
     90     NSLog(@"%@", cmps);
     91     
     92     // path是一个字符串常量,是不可变的
     93     path = @"/users/mj/test";
     94     // 判断是够为绝对路径(依据是前面有无/)
     95     NSLog(@"%i", [path isAbsolutePath]);
     96     NSLog(@"最后一个目录:%@", [path lastPathComponent]);
     97     // 删除最后一个目录
     98     NSLog(@"%@", [path stringByDeletingLastPathComponent]);
     99     // 在最后面拼接一个目录
    100     NSLog(@"%@", [path stringByAppendingPathComponent:@"abc"]);
    101 }
    102 
    103 #pragma mark 拓展名处理
    104 void extension() {
    105     NSString *str = @"/User/MJ/test.txt";
    106     
    107     NSLog(@"拓展名:%@", [str pathExtension]);
    108     // 删除拓展名
    109     NSLog(@"%@", [str stringByDeletingPathExtension]);
    110     // 添加拓展名
    111     NSLog(@"%@", [@"abc" stringByAppendingPathExtension:@"mp3"]);
    112 }
    113 
    114 #pragma mark 其他用法
    115 void other() {
    116     NSString *str = @"12";
    117     int a = [str intValue];
    118     NSLog(@"%i", a);
    119     
    120     // 计算字数,不是计算字符数
    121     NSLog(@"length=%zi", [@"我是字符串123" length]);
    122     
    123     // 取出对应的字符
    124     unichar c = [@"abc" characterAtIndex:0];
    125     NSLog(@"%c", c);
    126     
    127     // 返回C语言中的字符串
    128     const char *s = [@"abc" UTF8String];
    129     NSLog(@"%s", s);
    130 }
  • 相关阅读:
    从头梳理一下经常问到的 “零拷贝” 问题!
    Redis缓存使用中的热key问题
    使用Redis,你必须知道的21个注意要点
    一文理解 Redis 的核心原理与技术!
    大厂常问的Redis面试题
    三种不同场景下的 Kubernetes 服务调试方法
    Docker 和 Kubernetes:root 与特权
    DRBD详细解说及配置过程记录
    MySQL 高可用方案-PXC环境部署记录
    MySQL高可用方案
  • 原文地址:https://www.cnblogs.com/yif1991/p/5067005.html
Copyright © 2011-2022 走看看