(Foundation)NSObject 、 NSString 、 NSMutableString

1 重构Student和Book类

1.1 问题

本案例需要创建一个Book类,类中有一个整型price属性,用于记录书的价格。还需要创建一个Student类,类中有两个带参属性,它们是整型的年龄age和类Book类型的book,分别用于存储学生的年龄和学生正在学习的书,book属性带有copy参数,并且有一个study方法,用于显示年龄为age的学生学习价格为book.price的书。

在主程序中创建Student类的一个对象和Book类的两个对象,首先让Student类的对象拥有一个Book类的对象,然后让Student类的对象更换了拥有对象,换成另一个Book类对象。

1.2 步骤

实现此案例需要按照如下步骤进行。

步骤一:定义类Book

首先,在Day01工程中新添加Book.h文件,用于定义新的类Book。

代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. @interface Book : NSObject<NSCopying>
  3. @property int price;
  4. @end

在上述代码中,以下代码:

  1. @interface Book : NSObject<NSCopying>

定义了类Book,该类采用了NSCopying协议。

在上述代码中,以下代码:

  1. @property int price;

在Book类中定义了一个属性,是整型变量price,用于存储书的价格。

然后,在类Book的实现部分,即在Book.m文件中,添加两个方法的实现,一个是copyWithZone方法,该方法是在NSCopying协议中声明的方法,用于深拷贝;另一个是dealloc方法,由于使用ARC,该方法在本类中实际上没有任何实际意义,只是在类的对象销毁时,在控制台上输出一个提示。

代码如下所示:

  1. #import "Book.h"
  2. @implementation Book
  3. -(id)copyWithZone:(NSZone*)zone
  4. {
  5. Book* book = [[Book allocWithZone:zone] init];
  6. book.price = self.price;
  7. return book;
  8. }
  9. -(void)dealloc{
  10. NSLog(@"书对象销毁了 price:%d",self.price);
  11. }
  12. @end

上述代码中,copyWithZone方法不能在类外直接被调用,它是在向一个对象发送copy消息时,由copy消息调用。在该方法中,以下代码:

  1. Book* book = [[Book allocWithZone:zone] init];
  2. book.price = self.price;

生成一个本类对象的副本。需要注意的是分配空间使用的是allocWithZone方法。

上述代码中,dealloc方法也不能在类外直接被调用,它是在一个对象被release并且对象的引用计数为0时,由内存管理程序调用的方法。

步骤二:定义类Student

首先,在Day01工程中新添加Student.h文件,用于定义新的类Student。

代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. #import "Book.h"
  3. @interface Student : NSObject
  4. {
  5. }
  6. @property(nonatomic,assign) int age;
  7. @property(nonatomic,copy) Book* book;
  8. -(void)study;
  9. @end

在上述代码中,定义了类Student,在类中有两个带参属性。

一个属性是整型变量age,如下代码所示:

  1. @property(nonatomic,assign) int age;

用于存储学生的年龄。它有两个参数,一个是nonatomic,它代表对属性赋值的时候不加锁,即在多线程环境下访问时可能会出现数据错误,如果需要在多线程环境下运行,为保证数据不会出现错误,可使用atomic参数,它会在对属性赋值的时候加锁。另一个参数是assign,对于C语言的基本数据类型,只能选取这个参数。

另一个属性是book,如下代码所示:

  1. @property(nonatomic,copy) Book* book;

用于存储学生正在学习的书。它有两个参数,一个是nonatomic,另一个参数是copy,该参数一般用于NSObject类及其子类的对象,这些对象在赋值时实现深拷贝,即属性book指向的对象是赋值给它的对象的副本。

然后,在类Student的实现部分,即在Student.m文件中,添加dealloc方法和study方法的实现。

代码如下所示:

  1. #import "Student.h"
  2. @implementation Student
  3. -(void)dealloc{
  4. //将所有引用类型的属性在此释放掉
  5. NSLog(@"学生对象销毁了,dealloc方法执行了");
  6. }
  7. -(void)study{
  8. NSLog(@"学生 age:%d 学习书 price:%d 中的知识",self.age,self.book.price);
  9. }
  10. @end

由于使用ARC,dealloc方法在本类中实际上没有任何实际意义,只是在类的对象销毁时,在控制台上输出一个提示。

study方法要完成的工作是在控制台上输出学生的年龄和正在学习的书。

步骤三:在主程序中使用Student类和Book类

代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. #import "Student.h"
  3. int main(int argc, const char * argv[])
  4. {
  5. @autoreleasepool {
  6. // insert code here...
  7. Student* stu1 = [[Student alloc]init];
  8. stu1.age = 18;
  9. Book* sanguo = [[Book alloc]init];
  10. sanguo.price = 10;
  11. stu1.book = sanguo;//将书对象给学生对象
  12. Book* hongloumeng = [[Book alloc]init];
  13. hongloumeng.price = 20;
  14. stu1.book = hongloumeng;
  15. [stu1 study];
  16. }
  17. return 0;
  18. }

在上述代码中,以下代码:

  1. Student* stu1 = [[Student alloc]init];
  2. stu1.age = 18;

定义了一个Student类的对象stu1,并将stu1的age属性赋值为18。

在上述代码中,以下代码:

  1. Book* sanguo = [[Book alloc]init];
  2. sanguo.price = 10;
  3. stu1.book = sanguo;//将书对象给学生对象

首先,定义了一个Book类的对象sanguo,并将sanguo的price属性赋值为10。然后,将stu1的book属性赋值为sanguo。我们知道book属性有一个参数是copy,它会将赋值给它的sanguo对象生成一个副本,将副本赋值给stu1.book,这样指针sanguo和指针stu1.book将分别指向两个不同的地址,即实现深拷贝的功能。

在上述代码中,以下代码:

  1. Book* hongloumeng = [[Book alloc]init];
  2. hongloumeng.price = 20;
  3. stu1.book = hongloumeng;

首先,定义了一个Book类的对象hongloumeng,并将hongloumeng的price属性赋值为20。然后,将stu1的book属性重新赋值为hongloumeng。我们知道book属性有一个参数是copy,它会将赋值给它的hongloumeng对象生成一个副本,将副本赋值给stu1.book。但在赋值前stu1.book中存有sanguo的副本对象,此时将hongloumeng的副本对象赋值给它会造成sanguo副本的丢失,为了防止这一情况的发生,ARC将自动插入代码,向sanguo副本对象发送release消息,在本案例中,由于sanguo副本对象的引用计数值为1,所以向其发送release消息后,sanguo副本对象将被释放。

在上述代码中,以下代码:

  1. [stu1 study];

是向对象stu1发送study消息时,因为hongloumeng的引用计数为1,所以它能显示出hongloumeng的价格。

1.3 完整代码

本案例中,类Book声明,即Book.h文件,完整代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. @interface Book : NSObject<NSCopying>
  3. @property int price;
  4. @end

类Book实现,即Book.m文件,完整代码如下所示:

  1. #import "Book.h"
  2. @implementation Book
  3. -(id)copyWithZone:(NSZone*)zone
  4. {
  5. Book* book = [[Book allocWithZone:zone] init];
  6. book.price = self.price;
  7. return book;
  8. }
  9. -(void)dealloc{
  10. NSLog(@"书对象销毁了 price:%d",self.price);
  11. }
  12. @end

本案例中,类Student声明,即Student.h文件,完整代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. #import "Book.h"
  3. @interface Student : NSObject
  4. {
  5. }
  6. @property(nonatomic,assign) int age;
  7. @property(nonatomic,copy) Book* book;
  8. -(void)study;
  9. @end

类Student实现,即Student.m文件,完整代码如下所示:

  1. #import "Student.h"
  2. @implementation Student
  3. -(void)dealloc{
  4. //将所有引用类型的属性在此释放掉
  5. NSLog(@"学生对象销毁了,dealloc方法执行了");
  6. }
  7. -(void)study{
  8. NSLog(@"学生 age:%d 学习书 price:%d 中的知识",self.age,self.book.price);
  9. }
  10. @end

主程序,即main.m,完整代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. #import "Student.h"
  3. int main(int argc, const char * argv[])
  4. {
  5. @autoreleasepool {
  6. // insert code here...
  7. Student* stu1 = [[Student alloc]init];
  8. stu1.age = 18;
  9. Book* sanguo = [[Book alloc]init];
  10. sanguo.price = 10;
  11. stu1.book = sanguo;//将书对象给学生对象
  12. Book* hongloumeng = [[Book alloc]init];
  13. hongloumeng.price = 20;
  14. stu1.book = hongloumeng;
  15. [stu1 study];
  16. }
  17. return 0;
  18. }

2 重构Student类

2.1 问题

使用深拷贝的概念重构Student类,在类中包含以下实例变量int age、char gender、double salary信息,定义一个方法printInfo输出所有实例变量的值,在主函数中对Student类的对象进行赋值并输出。

2.2 步骤

实现此案例需要按照如下步骤进行。

步骤一:定义类Student

由于是对Student类的重构,所以在Day01-2工程中新添加Student.h文件用于定义新的类Student。

代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. @interface Student : NSObject<NSCopying>
  3. {
  4. }
  5. @property int age;
  6. @property char gender;
  7. @property double salary;
  8. -(void)printInfo;
  9. @end

上述代码中,以下代码:

  1. @interface Student : NSObject<NSCopying>

定义了类Student,该类采用了NSCopying协议。

在上述代码中,以下代码:

  1. @property int age;
  2. @property char gender;
  3. @property double salary;

在Student类中定义了三个属性,一个是整型变量age,用于存储学生的年龄,另一个是字符型变量gender,用于存储学生的性别,最后一个是双精度浮点型变量salary,用于存储学生的津贴。

上述代码中,以下代码:

  1. -(void)printInfo;

定义了类Student的一个方法printInfo,用于在控制台上输出三个属性的值。

然后,在类Student的实现部分,即在Student.m文件中,添加两个方法的实现,一个是copyWithZone方法,该方法是在NSCopying协议中声明的方法,用于深拷贝;另一个是printInfo方法。

代码如下所示:

  1. #import "Student.h"
  2. @implementation Student
  3. -(id)copyWithZone:(NSZone *)zone
  4. {
  5. Student *stu = [[Student allocWithZone:zone] init];
  6. stu.age = self.age;
  7. stu.gender = self.gender;
  8. stu.salary = self.salary;
  9. return stu;
  10. }
  11. -(void)printInfo
  12. {
  13. NSLog(@"age=%d", _age);
  14. NSLog(@"gender=%c", _gender);
  15. NSLog(@"salary=%lf", _salary);
  16. }
  17. @end

上述代码中,copyWithZone方法不能在类外直接被调用,它是在向一个对象发送copy消息时,由copy消息调用。在该方法中,以下代码:

  1. Student *stu = [[Student allocWithZone:zone] init];
  2. stu.age = self.age;
  3. stu.gender = self.gender;
  4. stu.salary = self.salary;

生成一个本类对象的副本。需要注意的是分配空间使用的是allocWithZone方法。

步骤二:在主程序中使用Student类

代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. #import "Student.h"
  3. int main(int argc, const char * argv[])
  4. {
  5. @autoreleasepool {
  6. // insert code here...
  7. Student *stu = [[Student alloc] init];
  8. stu.age = 25;
  9. stu.gender = ‘M‘;
  10. stu.salary = 5000;
  11. Student *stu1 = [stu copy];
  12. [stu1 printInfo];
  13. }
  14. return 0;
  15. }

上述代码中,以下代码:

  1. Student *stu = [[Student alloc] init];
  2. stu.age = 25;
  3. stu.gender = ‘M‘;
  4. stu.salary = 5000;

定义Student类的一个对象stu,并将对象stu的age属性赋值为25,将对象stu的gender属性赋值为‘M’,将对象stu的salary属性赋值为5000。

上述代码中,以下代码:

  1. Student *stu1 = [stu copy];
  2. [stu1 printInfo];

定义Student类的另一个对象stu1,并将对象stu1赋值为对象stu的副本。由于在Student类中采纳了NSCopying协议,并实现了NSCopying协议中的coptWithZone方法,所以在将[stu copy]赋值给stu1时,是先将对象stu生成一个副本,然后把stu副本的地址赋给指针stu1,这样就使得指针stu和stu1分别指向stu对象和stu对象的副本,实现了深拷贝的功能。

2.3 完整代码

本案例中,类Student声明,即Student1.h文件,完整代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. @interface Student : NSObject<NSCopying>
  3. {
  4. }
  5. @property int age;
  6. @property char gender;
  7. @property double salary;
  8. -(void)printInfo;
  9. @end

类Student实现,即Student.m文件,完整代码如下所示:

  1. #import "Student.h"
  2. @implementation Student
  3. -(id)copyWithZone:(NSZone *)zone
  4. {
  5. Student *stu = [[Student allocWithZone:zone] init];
  6. stu.age = self.age;
  7. stu.gender = self.gender;
  8. stu.salary = self.salary;
  9. return stu;
  10. }
  11. -(void)printInfo
  12. {
  13. NSLog(@"age=%d", _age);
  14. NSLog(@"gender=%c", _gender);
  15. NSLog(@"salary=%lf", _salary);
  16. }
  17. @end

主程序,即main.m,完整代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. #import "Student.h"
  3. int main(int argc, const char * argv[])
  4. {
  5. @autoreleasepool {
  6. // insert code here...
  7. Student *stu = [[Student alloc] init];
  8. stu.age = 25;
  9. stu.gender = ‘M‘;
  10. stu.salary = 5000;
  11. Student *stu1 = [stu copy];
  12. [stu1 printInfo];
  13. }
  14. return 0;
  15. }

3 模拟系统登录

3.1 问题

编制模拟系统登录程序。从控制台输入用户名、密码登录信息,与保存在文件中的用户名、密码进行对比匹配,如果匹配就显示登录成功,否则显示登录失败。

3.2 步骤

实现此案例需要按照如下步骤进行。

步骤一:从控制台输入用户名

代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. int main(int argc, const char * argv[])
  3. {
  4. @autoreleasepool {
  5. // insert code here...
  6. char name[100];
  7. NSLog(@"请输入用户名:");
  8. scanf("%s", name);
  9. NSString *fileName = [NSString stringWithCString:name encoding:NSASCIIStringEncoding];
  10. }
  11. return 0;
  12. }

上述代码中,以下代码:

  1. NSString *fileName = [NSString stringWithCString:name encoding:NSASCIIStringEncoding];

是使用NSString类的stringWithCString: encoding:方法,将字符数组name转换成NSString类的对象。stringWithCString: encoding:方法有两个实参,第一个实参是要转换的字符数组名;第二个实参为要转换字符数组的编码方式,对于char型数组,编码方式为NSASCIIStringEncoding。

步骤二:从控制台输入密码

代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. int main(int argc, const char * argv[])
  3. {
  4. @autoreleasepool {
  5. // insert code here...
  6. char name[100];
  7. NSLog(@"请输入用户名:");
  8. scanf("%s", name);
  9. NSString *fileName = [NSString stringWithCString:name encoding:NSASCIIStringEncoding];
  10. char password[100];
  11. NSLog(@"请输入密码:");
  12. scanf("%s", password);
  13. NSString *filePassword = [NSString stringWithCString:password encoding:NSASCIIStringEncoding];
  14. }
  15. return 0;
  16. }

步骤三:从文件中读取用户名

代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. int main(int argc, const char * argv[])
  3. {
  4. @autoreleasepool {
  5. // insert code here...
  6. char name[100];
  7. NSLog(@"请输入用户名:");
  8. scanf("%s", name);
  9. NSString *fileName = [NSString stringWithCString:name encoding:NSASCIIStringEncoding];
  10. char password[100];
  11. NSLog(@"请输入密码:");
  12. scanf("%s", password);
  13. NSString *filePassword = [NSString stringWithCString:password encoding:NSASCIIStringEncoding];
  14. NSError *error = [[NSError alloc] init];
  15. NSString *fileName1 = [NSString stringWithContentsOfFile:@"/users/tarena/desktop/name.txt" encoding:NSUTF8StringEncoding error:&error];
  16. }
  17. return 0;
  18. }

上述代码中,以下代码:

  1. NSError *error = [[NSError alloc] init];
  2. NSString *fileName1 = [NSString stringWithContentsOfFile:@"/users/tarena/desktop/name.txt" encoding:NSUTF8StringEncoding error:&error];

用指定的文件@"/users/tarena/desktop/name.txt"中的内容创建NSString类的对象,从文件中读入的用户名放入对象fileName1。创建对象的方法是使用NSString类的stringWithContentsOfFile: encoding: error:方法,该方法有三个实参,第一个实参是指定文件的含路径文件名;第二个实参是文件内容的编码方式;第三个实参是NSError类的对象,用于获取错误信息。

步骤四:判断用户名是否匹配

代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. int main(int argc, const char * argv[])
  3. {
  4. @autoreleasepool {
  5. // insert code here...
  6. char name[100];
  7. NSLog(@"请输入用户名:");
  8. scanf("%s", name);
  9. NSString *fileName = [NSString stringWithCString:name encoding:NSASCIIStringEncoding];
  10. char password[100];
  11. NSLog(@"请输入密码:");
  12. scanf("%s", password);
  13. NSString *filePassword = [NSString stringWithCString:password encoding:NSASCIIStringEncoding];
  14. NSError *error = [[NSError alloc] init];
  15. NSString *fileName1 = [NSString stringWithContentsOfFile:@"/users/tarena/desktop/name.txt" encoding:NSUTF8StringEncoding error:&error];
  16. if ([fileName1 isEqualToString:fileName] == YES)
  17. {
  18. NSString *filePassword1 = [NSString stringWithContentsOfFile:@"/users/tarena/desktop/password.txt" encoding:NSUTF8StringEncoding error: &error];
  19. if ([filePassword1 isEqualToString:filePassword] == YES)
  20. NSLog(@"登录成功");
  21. else
  22. NSLog(@"用户名或密码错误");
  23. }
  24. else
  25. NSLog(@"用户名或密码错误");
  26. }
  27. return 0;
  28. }

上述代码中,以下代码:

  1. if ([fileName1 isEqualToString:fileName] == YES)

是判断从控制台输入的用户名fileName与从文件中读入的用户名fileName1是否匹配,判断的方法是使用NSString类的isEqualToString方法,该方法有一个实参,是要对比的NSString对象。如果两个对象相同,则返回为真;否则为假。

上述代码中,以下代码:

  1. NSString *filePassword1 = [NSString stringWithContentsOfFile:@"/users/tarena/desktop/password.txt" encoding:NSUTF8StringEncoding error: &error];

用指定的文件@"/users/tarena/desktop/password.txt"中的内容创建NSString类的对象,从文件中读入的密码放入对象filePassword1。

上述代码中,以下代码:

  1. if ([filePassword1 isEqualToString:filePassword] == YES)
  2. NSLog(@"登录成功");
  3. else
  4. NSLog(@"用户名或密码错误");

是判断从控制台输入的密码filePassword与从文件中读入的密码filePassword1是否匹配。如果匹配,则在控制台上输出“登录成功”;否则输出“用户名或密码错误”。

3.3 完整代码

本案例的完整代码如下:

  1. #import <Foundation/Foundation.h>
  2. int main(int argc, const char * argv[])
  3. {
  4. @autoreleasepool {
  5. // insert code here...
  6. char name[100];
  7. NSLog(@"请输入用户名:");
  8. scanf("%s", name);
  9. NSString *fileName = [NSString stringWithCString:name encoding:NSASCIIStringEncoding];
  10. char password[100];
  11. NSLog(@"请输入密码:");
  12. scanf("%s", password);
  13. NSString *filePassword = [NSString stringWithCString:password encoding:NSASCIIStringEncoding];
  14. NSError *error = [[NSError alloc] init];
  15. NSString *fileName1 = [NSString stringWithContentsOfFile:@"/users/tarena/desktop/name.txt" encoding:NSUTF8StringEncoding error:&error];
  16. if ([fileName1 isEqualToString:fileName] == YES)
  17. {
  18. NSString *filePassword1 = [NSString stringWithContentsOfFile:@"/users/tarena/desktop/password.txt" encoding:NSUTF8StringEncoding error:&error];
  19. if ([filePassword1 isEqualToString:filePassword] == YES)
  20. NSLog(@"登录成功");
  21. else
  22. NSLog(@"用户名或密码错误");
  23. }
  24. else
  25. NSLog(@"用户名或密码错误");
  26. }
  27. return 0;
  28. }

4 根据身份证号码,求出生年月日和所属省份

4.1 问题

身份证是公民用于证明持有人身份的证件。

1984年4月,我国开始实行居民身份证制度,第一代居民身份证采用印刷和照相翻拍技术塑封而成,比较容易被伪造。

2003年6月,《中华人民共和国居民身份证法》规定居住在中华人民共和国境内的年满十六周岁的中国公民,应当申请领取居民身份证;未满十六周岁的中国公民,也可以依照本法的规定申请领取居民身份证。

2004年3月起我国正式开始为居民换发内藏非接触式IC卡智能芯片的第二代居民身份证,第二代身份证表面采用防伪膜和印刷防伪技术,使用个人彩色照片,而且内置了数字芯片,采用了数字防伪措施,存有个人图像和信息,可以用机器读取。十六周岁至二十五周岁的,发给有效期十年的居民身份证;二十六周岁至四十五周岁的,发给有效期二十年的居民身份证;四十六周岁以上的,发给长期有效的居民身份证;未满十六周岁的公民,自愿申请领取居民身份证的,发给有效期五年的居民身份证。

自2012年1月1日起,公民申请领取、换领、补领居民身份证,应当登记指纹信息。

4.2 方案

身份证上有一个18位的身份证号,这个号码依据《中华人民共和国国家标准 GB 11643-1999》是这样定义的,从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。出生日期码表示持证人出生的年、月、日。

依据以上的知识,从控制台输入一个含有18位数字的字符串,截取其中的出生日期码,就可以得到持证人的出生日期。

六位数字地址码是这样定义的:头两位表示省份,中间两位表示市,最后两位表示县。这样只要截取其中的头两位,就可知其所在的省份。具体规定如下:

北京|11,天津|12,河北|13,山西|14,内蒙|15,辽宁|21,吉林|22,黑龙江|23,上海|31,江苏|32,浙江|33,安徽|34,福建|35,江西|36,山东|37,河南|41,湖北|42,湖南|43,广东|44,广西|45,海南|46,重庆|50,四川|51,贵州|52,云南|53,西藏|54,陕西|61,甘肃|62,青海|63,宁夏|64,新疆|65,台湾|71,香港|81,澳门|82。

4.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:从控制台输入某人的身份证号

代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. int main(int argc, const char * argv[])
  3. {
  4. @autoreleasepool {
  5. char id[19] = {};
  6. NSLog(@"请输入身份证号:");
  7. scanf("%s", id);
  8. NSString *idString = [NSString stringWithCString:id encoding:NSASCIIStringEncoding];
  9. }
  10. return 0;
  11. }

步骤二:截取出生日期

代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. int main(int argc, const char * argv[])
  3. {
  4. @autoreleasepool {
  5. char id[19] = {};
  6. NSLog(@"请输入身份证号:");
  7. scanf("%s", id);
  8. NSString *idString = [NSString stringWithCString:id encoding:NSASCIIStringEncoding];
  9. NSRange birthday = {6, 8};
  10. NSString *birthdayString = [idString substringWithRange:birthday];
  11. NSLog(@"出生日期为:%@", birthdayString);
  12. }
  13. return 0;
  14. }

上述代码中,以下代码:

  1. NSRange birthday = {6, 8};

定义一个范围birthday,在本案例中这个范围的意义是,从身份证号码第7位开始,连续8个数字。程序中是6,因为字符串中的字符从0开始计算,所以到6时是第7位。

上述代码中,以下代码:

  1. NSString *birthdayString = [idString substringWithRange:birthday];

是截取身份证字符串指定范围内的数字,使用NSString类的substringWithRange方法实现,该方法带有一个实参birthday,是要截取身份证号码从第7位开始,连续8个数字,它们正好是持证人的出生年月日。

步骤三:截取所属省份

代码如下所示:

  1. #import <Foundation/Foundation.h>
  2. int main(int argc, const char * argv[])
  3. {
  4. @autoreleasepool {
  5. char id[19] = {};
  6. NSLog(@"请输入身份证号:");
  7. scanf("%s", id);
  8. NSString *idString = [NSString stringWithCString:id encoding:NSASCIIStringEncoding];
  9. NSRange birthday = {6, 8};
  10. NSString *birthdayString = [idString substringWithRange:birthday];
  11. NSLog(@"出生日期为:%@", birthdayString);
  12. NSString *idData[][2] = {
  13. {@"北京", @"11"},
  14. {@"天津", @"12"},
  15. {@"河北", @"13"},
  16. {@"山西", @"14"},
  17. {@"内蒙", @"15"},
  18. {@"辽宁", @"21"},
  19. {@"吉林", @"22"},
  20. {@"黑龙江",@"23"},
  21. {@"上海", @"31"},
  22. {@"江苏", @"32"},
  23. {@"浙江", @"33"},
  24. {@"安徽", @"34"},
  25. {@"福建", @"35"},
  26. {@"江西", @"36"},
  27. {@"山东", @"37"},
  28. {@"河南", @"41"},
  29. {@"湖北", @"42"},
  30. {@"湖南", @"43"},
  31. {@"广东", @"44"},
  32. {@"广西", @"45"},
  33. {@"海南", @"46"},
  34. {@"重庆", @"50"},
  35. {@"四川", @"51"},
  36. {@"贵州", @"52"},
  37. {@"云南", @"53"},
  38. {@"西藏", @"54"},
  39. {@"陕西", @"61"},
  40. {@"甘肃", @"62"},
  41. {@"青海", @"63"},
  42. {@"宁夏", @"64"},
  43. {@"新疆", @"65"},
  44. {@"台湾", @"71"},
  45. {@"香港", @"81"},
  46. {@"澳门", @"82"}
  47. };
  48. NSString *city = [idString substringToIndex:2];
  49. for (int i = 0; i < 5; i++)
  50. {
  51. NSString *idCity = idData[i][1];
  52. if ([city isEqualToString:idCity] == YES)
  53. {
  54. NSLog(@"所属省份为:%@", idData[i][0]);
  55. break;
  56. }
  57. }
  58. }
  59. return 0;
  60. }

上述代码中,以下代码:

  1. NSString *idData[][2] = {
  2. {@"北京", @"11"},
  3. {@"天津", @"12"},
  4. {@"河北", @"13"},
  5. {@"山西", @"14"},
  6. {@"内蒙", @"15"},
  7. {@"辽宁", @"21"},
  8. {@"吉林", @"22"},
  9. {@"黑龙江",@"23"},
  10. {@"上海", @"31"},
  11. {@"江苏", @"32"},
  12. {@"浙江", @"33"},
  13. {@"安徽", @"34"},
  14. {@"福建", @"35"},
  15. {@"江西", @"36"},
  16. {@"山东", @"37"},
  17. {@"河南", @"41"},
  18. {@"湖北", @"42"},
  19. {@"湖南", @"43"},
  20. {@"广东", @"44"},
  21. {@"广西", @"45"},
  22. {@"海南", @"46"},
  23. {@"重庆", @"50"},
  24. {@"四川", @"51"},
  25. {@"贵州", @"52"},
  26. {@"云南", @"53"},
  27. {@"西藏", @"54"},
  28. {@"陕西", @"61"},
  29. {@"甘肃", @"62"},
  30. {@"青海", @"63"},
  31. {@"宁夏", @"64"},
  32. {@"新疆", @"65"},
  33. {@"台湾", @"71"},
  34. {@"香港", @"81"},
  35. {@"澳门", @"82"}
  36. };

使用一个二维数组,建立省份名与代码之间的联系。

上述代码中,以下代码:

  1. NSString *city = [idString substringToIndex:2];

是从身份证字符串中截取前两位地址码,使用NSString类的substringToIndex方法实现,该方法带有一个实参,表示截取从字符串第一个字符到该实参之间所有字符,形成一个新的字符串。

上述代码中,以下代码:

  1. for (int i = 0; i < 34; i++)
  2. {
  3. NSString *idCity = idData[i][1];
  4. if ([city isEqualToString:idCity] == YES)
  5. {
  6. NSLog(@"所属省份为:%@", idData[i][0]);
  7. break;
  8. }
  9. }

使用一个循环遍历数组,查找身份证上的地址码对应的省份名称。以下代码:

  1. NSString *idCity = idData[i][1];

首先从数组中读取一个地址码。以下代码:

  1. if ([city isEqualToString:idCity] == YES)

判断该地址码与从身份证上截取的地址码是否相同,如果相同,则在控制台上输出该地址码对应的省份名称并结束遍历数组;否则继续遍历数组。

4.4 完整代码

本案例的完整代码如下:

  1. #import <Foundation/Foundation.h>
  2. int main(int argc, const char * argv[])
  3. {
  4. @autoreleasepool {
  5. char id[19] = {};
  6. NSLog(@"请输入身份证号:");
  7. scanf("%s", id);
  8. NSString *idString = [NSString stringWithCString:id encoding:NSASCIIStringEncoding];
  9. NSRange birthday = {6, 8};
  10. NSString *birthdayString = [idString substringWithRange:birthday];
  11. NSLog(@"出生日期为:%@", birthdayString);
  12. NSString *idData[][2] = {
  13. {@"北京", @"11"},
  14. {@"天津", @"12"},
  15. {@"河北", @"13"},
  16. {@"山西", @"14"},
  17. {@"内蒙", @"15"},
  18. {@"辽宁", @"21"},
  19. {@"吉林", @"22"},
  20. {@"黑龙江",@"23"},
  21. {@"上海", @"31"},
  22. {@"江苏", @"32"},
  23. {@"浙江", @"33"},
  24. {@"安徽", @"34"},
  25. {@"福建", @"35"},
  26. {@"江西", @"36"},
  27. {@"山东", @"37"},
  28. {@"河南", @"41"},
  29. {@"湖北", @"42"},
  30. {@"湖南", @"43"},
  31. {@"广东", @"44"},
  32. {@"广西", @"45"},
  33. {@"海南", @"46"},
  34. {@"重庆", @"50"},
  35. {@"四川", @"51"},
  36. {@"贵州", @"52"},
  37. {@"云南", @"53"},
  38. {@"西藏", @"54"},
  39. {@"陕西", @"61"},
  40. {@"甘肃", @"62"},
  41. {@"青海", @"63"},
  42. {@"宁夏", @"64"},
  43. {@"新疆", @"65"},
  44. {@"台湾", @"71"},
  45. {@"香港", @"81"},
  46. {@"澳门", @"82"}
  47. };
  48. NSString *city = [idString substringToIndex:2];
  49. for (int i = 0; i < 34; i++)
  50. {
  51. NSString *idCity = idData[i][1];
  52. if ([city isEqualToString:idCity] == YES)
  53. {
  54. NSLog(@"所属省份为:%@", idData[i][0]);
  55. break;
  56. }
  57. }
  58. }
  59. return 0;
  60. }
时间: 2024-10-20 01:23:25

(Foundation)NSObject 、 NSString 、 NSMutableString的相关文章

黑 马 程 序 员_视频学习总结&lt;Objective-C&gt;----03 self、NSString、@property和@synthesize、id

---------------------- ASP.Net+Unity开发..Net培训.期待与您交流! ---------------------- 一.self 1.谁调用了当前方法,self就代表谁.两种情况:self出现在对象方法里,self就代表对象:self出现在类方法里,self就代表类. 2.对象方法利用“self→成员变量名”访问当前对象内部成员变量. 3.[self 方法名]可以调用其它对象方法.类方法. 二.NSString 1.NSString简介:NSString是一

NSData、NSString 、 NSFileManager

1 NSData和NSMutableData的基本使用 1.1 问题 NSData类是IOS提供的用于以二进制的形式操作文件数据的类,NSData有两个常用的属性length和bytes,length表示字节的数量,bytes起始字节的位置是一个指针类型,本案例演示NSData和NSMutableData的基本使用,使用NSData /NSMutableData对象保存一个C语言字符串. 1.2 方案 首先使用Xcode创建一个命令行项目,在main函数中创建一个NSData对象data,使用i

Foundation 框架之——NSString、NSMutableString 一

1 //字符串的创建 2 NSString *s1 = @"Rose"; 3 4 // 作用相当于s1,基本不用 5 // 警告:Using 'initWithString:' with a literal is redundant 6 // 用“initWithString:“是多余的 7 NSString *s2 = [[NSString alloc] initWithString:@"Rose"]; 8 9 10 NSString *s3 = [[NSStri

Foundation 框架中NSString and NSMutableString的详解

NSString:不可变字符串 创建字符串的最简单的方式: NSString *str = @"itcast"; // 这个创建的是OC字符串 oc中的字符串都是NSString类的对象 char *name = "itcast"; // 这个是c语言字符串 NSLog(@"我在%@上课",str): // %@是用来输出oc对象的 NSLog(@"%s",name); // %s是用来输出c语言字符串 使用oc字符串的好处:

NSDate、NSString、long转化

- (NSDate *)dateFromString:(NSString *)dateString{ NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat: @"yyyy-MM-dd HH:mm:ss"]; NSDate *destDate= [dateFormatter dateFromString:dateString]; return destDa

Objective-C学习笔记_NSString、NSArray、NSNumber

Foundation框架 Foundation框架是Cocoa编程.iOS编程的基础框架,包括:字符串.集合.日期.时间等基础类. 一.NSString和NSMutableString的使? C语?,字符串是由char(ASCII码)字符组成. Objective-C,字符串是由unichar(Unicode)字符组成. NSString:不可变字符串,继承NSObject:即创建之后,内容和长度不能更改,其字符串截取.拼接等常用方法返回值类型为(NSString *),本质是得到一个新的字符串

Objective-c中对象的Copy、MutableCopy、浅拷贝、深拷贝

对象的复制就是复制一个对象作为副本,他会开辟一块新的内存(堆内存)来存储副本对象,就像复制文件一样,即源对象和副本对象是两块不同的内存区域.对象要具备复制功能,必须实现<NSCopying>协议或者<NSMutableCopying>协议,常用的可复制对象有:NSNumber.NSString.NSMutableString.NSArray.NSMutableArray.NSDictionary.NSMutableDictionary copy:产生对象的副本是不可变的 mutab

网络HTTP、JSON、XML解析等 复习

一.一个HTTP请求的基本要素1.请求URL:客户端通过哪个路径找到服务器 2.请求参数:客户端发送给服务器的数据* 比如登录时需要发送的用户名和密码 3.返回结果:服务器返回给客户端的数据* 一般是JSON数据或者XML数据 二.基本的HTTP请求的步骤(移动客户端)1.拼接"请求URL" + "?" + "请求参数"* 请求参数的格式:参数名=参数值* 多个请求参数之间用&隔开:参数名1=参数值1&参数名2=参数值2* 比如:

黑马程序员-OC学习笔记之NSString与NSMutableString

---------------------- IOS开发.Android培训.期待与您交流! ---------------------- 一.NSString与NSMutableString 相信大家对NSString类都不陌生,它是OC中提供的字符串类,它的对象中的字符串都是不可变的,而它的子类NSMutableString类的对象中的字符串就是可变的.什么是可变与不可变呢?二者的区别就是在已经创建的一个字符串对象中,在程序中能不能更改字符串,比如拼接新的字符串,可变的可以在原字符串中更改,