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。
代码如下所示:
- #import <Foundation/Foundation.h>
- @interface Book : NSObject<NSCopying>
- @property int price;
- @end
在上述代码中,以下代码:
- @interface Book : NSObject<NSCopying>
定义了类Book,该类采用了NSCopying协议。
在上述代码中,以下代码:
- @property int price;
在Book类中定义了一个属性,是整型变量price,用于存储书的价格。
然后,在类Book的实现部分,即在Book.m文件中,添加两个方法的实现,一个是copyWithZone方法,该方法是在NSCopying协议中声明的方法,用于深拷贝;另一个是dealloc方法,由于使用ARC,该方法在本类中实际上没有任何实际意义,只是在类的对象销毁时,在控制台上输出一个提示。
代码如下所示:
- #import "Book.h"
- @implementation Book
- -(id)copyWithZone:(NSZone*)zone
- {
- Book* book = [[Book allocWithZone:zone] init];
- book.price = self.price;
- return book;
- }
- -(void)dealloc{
- NSLog(@"书对象销毁了 price:%d",self.price);
- }
- @end
上述代码中,copyWithZone方法不能在类外直接被调用,它是在向一个对象发送copy消息时,由copy消息调用。在该方法中,以下代码:
- Book* book = [[Book allocWithZone:zone] init];
- book.price = self.price;
生成一个本类对象的副本。需要注意的是分配空间使用的是allocWithZone方法。
上述代码中,dealloc方法也不能在类外直接被调用,它是在一个对象被release并且对象的引用计数为0时,由内存管理程序调用的方法。
步骤二:定义类Student
首先,在Day01工程中新添加Student.h文件,用于定义新的类Student。
代码如下所示:
- #import <Foundation/Foundation.h>
- #import "Book.h"
- @interface Student : NSObject
- {
- }
- @property(nonatomic,assign) int age;
- @property(nonatomic,copy) Book* book;
- -(void)study;
- @end
在上述代码中,定义了类Student,在类中有两个带参属性。
一个属性是整型变量age,如下代码所示:
- @property(nonatomic,assign) int age;
用于存储学生的年龄。它有两个参数,一个是nonatomic,它代表对属性赋值的时候不加锁,即在多线程环境下访问时可能会出现数据错误,如果需要在多线程环境下运行,为保证数据不会出现错误,可使用atomic参数,它会在对属性赋值的时候加锁。另一个参数是assign,对于C语言的基本数据类型,只能选取这个参数。
另一个属性是book,如下代码所示:
- @property(nonatomic,copy) Book* book;
用于存储学生正在学习的书。它有两个参数,一个是nonatomic,另一个参数是copy,该参数一般用于NSObject类及其子类的对象,这些对象在赋值时实现深拷贝,即属性book指向的对象是赋值给它的对象的副本。
然后,在类Student的实现部分,即在Student.m文件中,添加dealloc方法和study方法的实现。
代码如下所示:
- #import "Student.h"
- @implementation Student
- -(void)dealloc{
- //将所有引用类型的属性在此释放掉
- NSLog(@"学生对象销毁了,dealloc方法执行了");
- }
- -(void)study{
- NSLog(@"学生 age:%d 学习书 price:%d 中的知识",self.age,self.book.price);
- }
- @end
由于使用ARC,dealloc方法在本类中实际上没有任何实际意义,只是在类的对象销毁时,在控制台上输出一个提示。
study方法要完成的工作是在控制台上输出学生的年龄和正在学习的书。
步骤三:在主程序中使用Student类和Book类
代码如下所示:
- #import <Foundation/Foundation.h>
- #import "Student.h"
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- // insert code here...
- Student* stu1 = [[Student alloc]init];
- stu1.age = 18;
- Book* sanguo = [[Book alloc]init];
- sanguo.price = 10;
- stu1.book = sanguo;//将书对象给学生对象
- Book* hongloumeng = [[Book alloc]init];
- hongloumeng.price = 20;
- stu1.book = hongloumeng;
- [stu1 study];
- }
- return 0;
- }
在上述代码中,以下代码:
- Student* stu1 = [[Student alloc]init];
- stu1.age = 18;
定义了一个Student类的对象stu1,并将stu1的age属性赋值为18。
在上述代码中,以下代码:
- Book* sanguo = [[Book alloc]init];
- sanguo.price = 10;
- stu1.book = sanguo;//将书对象给学生对象
首先,定义了一个Book类的对象sanguo,并将sanguo的price属性赋值为10。然后,将stu1的book属性赋值为sanguo。我们知道book属性有一个参数是copy,它会将赋值给它的sanguo对象生成一个副本,将副本赋值给stu1.book,这样指针sanguo和指针stu1.book将分别指向两个不同的地址,即实现深拷贝的功能。
在上述代码中,以下代码:
- Book* hongloumeng = [[Book alloc]init];
- hongloumeng.price = 20;
- 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副本对象将被释放。
在上述代码中,以下代码:
- [stu1 study];
是向对象stu1发送study消息时,因为hongloumeng的引用计数为1,所以它能显示出hongloumeng的价格。
1.3 完整代码
本案例中,类Book声明,即Book.h文件,完整代码如下所示:
- #import <Foundation/Foundation.h>
- @interface Book : NSObject<NSCopying>
- @property int price;
- @end
类Book实现,即Book.m文件,完整代码如下所示:
- #import "Book.h"
- @implementation Book
- -(id)copyWithZone:(NSZone*)zone
- {
- Book* book = [[Book allocWithZone:zone] init];
- book.price = self.price;
- return book;
- }
- -(void)dealloc{
- NSLog(@"书对象销毁了 price:%d",self.price);
- }
- @end
本案例中,类Student声明,即Student.h文件,完整代码如下所示:
- #import <Foundation/Foundation.h>
- #import "Book.h"
- @interface Student : NSObject
- {
- }
- @property(nonatomic,assign) int age;
- @property(nonatomic,copy) Book* book;
- -(void)study;
- @end
类Student实现,即Student.m文件,完整代码如下所示:
- #import "Student.h"
- @implementation Student
- -(void)dealloc{
- //将所有引用类型的属性在此释放掉
- NSLog(@"学生对象销毁了,dealloc方法执行了");
- }
- -(void)study{
- NSLog(@"学生 age:%d 学习书 price:%d 中的知识",self.age,self.book.price);
- }
- @end
主程序,即main.m,完整代码如下所示:
- #import <Foundation/Foundation.h>
- #import "Student.h"
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- // insert code here...
- Student* stu1 = [[Student alloc]init];
- stu1.age = 18;
- Book* sanguo = [[Book alloc]init];
- sanguo.price = 10;
- stu1.book = sanguo;//将书对象给学生对象
- Book* hongloumeng = [[Book alloc]init];
- hongloumeng.price = 20;
- stu1.book = hongloumeng;
- [stu1 study];
- }
- return 0;
- }
2 重构Student类
2.1 问题
使用深拷贝的概念重构Student类,在类中包含以下实例变量int age、char gender、double salary信息,定义一个方法printInfo输出所有实例变量的值,在主函数中对Student类的对象进行赋值并输出。
2.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:定义类Student
由于是对Student类的重构,所以在Day01-2工程中新添加Student.h文件用于定义新的类Student。
代码如下所示:
- #import <Foundation/Foundation.h>
- @interface Student : NSObject<NSCopying>
- {
- }
- @property int age;
- @property char gender;
- @property double salary;
- -(void)printInfo;
- @end
上述代码中,以下代码:
- @interface Student : NSObject<NSCopying>
定义了类Student,该类采用了NSCopying协议。
在上述代码中,以下代码:
- @property int age;
- @property char gender;
- @property double salary;
在Student类中定义了三个属性,一个是整型变量age,用于存储学生的年龄,另一个是字符型变量gender,用于存储学生的性别,最后一个是双精度浮点型变量salary,用于存储学生的津贴。
上述代码中,以下代码:
- -(void)printInfo;
定义了类Student的一个方法printInfo,用于在控制台上输出三个属性的值。
然后,在类Student的实现部分,即在Student.m文件中,添加两个方法的实现,一个是copyWithZone方法,该方法是在NSCopying协议中声明的方法,用于深拷贝;另一个是printInfo方法。
代码如下所示:
- #import "Student.h"
- @implementation Student
- -(id)copyWithZone:(NSZone *)zone
- {
- Student *stu = [[Student allocWithZone:zone] init];
- stu.age = self.age;
- stu.gender = self.gender;
- stu.salary = self.salary;
- return stu;
- }
- -(void)printInfo
- {
- NSLog(@"age=%d", _age);
- NSLog(@"gender=%c", _gender);
- NSLog(@"salary=%lf", _salary);
- }
- @end
上述代码中,copyWithZone方法不能在类外直接被调用,它是在向一个对象发送copy消息时,由copy消息调用。在该方法中,以下代码:
- Student *stu = [[Student allocWithZone:zone] init];
- stu.age = self.age;
- stu.gender = self.gender;
- stu.salary = self.salary;
生成一个本类对象的副本。需要注意的是分配空间使用的是allocWithZone方法。
步骤二:在主程序中使用Student类
代码如下所示:
- #import <Foundation/Foundation.h>
- #import "Student.h"
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- // insert code here...
- Student *stu = [[Student alloc] init];
- stu.age = 25;
- stu.gender = ‘M‘;
- stu.salary = 5000;
- Student *stu1 = [stu copy];
- [stu1 printInfo];
- }
- return 0;
- }
上述代码中,以下代码:
- Student *stu = [[Student alloc] init];
- stu.age = 25;
- stu.gender = ‘M‘;
- stu.salary = 5000;
定义Student类的一个对象stu,并将对象stu的age属性赋值为25,将对象stu的gender属性赋值为‘M’,将对象stu的salary属性赋值为5000。
上述代码中,以下代码:
- Student *stu1 = [stu copy];
- [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文件,完整代码如下所示:
- #import <Foundation/Foundation.h>
- @interface Student : NSObject<NSCopying>
- {
- }
- @property int age;
- @property char gender;
- @property double salary;
- -(void)printInfo;
- @end
类Student实现,即Student.m文件,完整代码如下所示:
- #import "Student.h"
- @implementation Student
- -(id)copyWithZone:(NSZone *)zone
- {
- Student *stu = [[Student allocWithZone:zone] init];
- stu.age = self.age;
- stu.gender = self.gender;
- stu.salary = self.salary;
- return stu;
- }
- -(void)printInfo
- {
- NSLog(@"age=%d", _age);
- NSLog(@"gender=%c", _gender);
- NSLog(@"salary=%lf", _salary);
- }
- @end
主程序,即main.m,完整代码如下所示:
- #import <Foundation/Foundation.h>
- #import "Student.h"
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- // insert code here...
- Student *stu = [[Student alloc] init];
- stu.age = 25;
- stu.gender = ‘M‘;
- stu.salary = 5000;
- Student *stu1 = [stu copy];
- [stu1 printInfo];
- }
- return 0;
- }
3 模拟系统登录
3.1 问题
编制模拟系统登录程序。从控制台输入用户名、密码登录信息,与保存在文件中的用户名、密码进行对比匹配,如果匹配就显示登录成功,否则显示登录失败。
3.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:从控制台输入用户名
代码如下所示:
- #import <Foundation/Foundation.h>
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- // insert code here...
- char name[100];
- NSLog(@"请输入用户名:");
- scanf("%s", name);
- NSString *fileName = [NSString stringWithCString:name encoding:NSASCIIStringEncoding];
- }
- return 0;
- }
上述代码中,以下代码:
- NSString *fileName = [NSString stringWithCString:name encoding:NSASCIIStringEncoding];
是使用NSString类的stringWithCString: encoding:方法,将字符数组name转换成NSString类的对象。stringWithCString: encoding:方法有两个实参,第一个实参是要转换的字符数组名;第二个实参为要转换字符数组的编码方式,对于char型数组,编码方式为NSASCIIStringEncoding。
步骤二:从控制台输入密码
代码如下所示:
- #import <Foundation/Foundation.h>
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- // insert code here...
- char name[100];
- NSLog(@"请输入用户名:");
- scanf("%s", name);
- NSString *fileName = [NSString stringWithCString:name encoding:NSASCIIStringEncoding];
- char password[100];
- NSLog(@"请输入密码:");
- scanf("%s", password);
- NSString *filePassword = [NSString stringWithCString:password encoding:NSASCIIStringEncoding];
- }
- return 0;
- }
步骤三:从文件中读取用户名
代码如下所示:
- #import <Foundation/Foundation.h>
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- // insert code here...
- char name[100];
- NSLog(@"请输入用户名:");
- scanf("%s", name);
- NSString *fileName = [NSString stringWithCString:name encoding:NSASCIIStringEncoding];
- char password[100];
- NSLog(@"请输入密码:");
- scanf("%s", password);
- NSString *filePassword = [NSString stringWithCString:password encoding:NSASCIIStringEncoding];
- NSError *error = [[NSError alloc] init];
- NSString *fileName1 = [NSString stringWithContentsOfFile:@"/users/tarena/desktop/name.txt" encoding:NSUTF8StringEncoding error:&error];
- }
- return 0;
- }
上述代码中,以下代码:
- NSError *error = [[NSError alloc] init];
- 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类的对象,用于获取错误信息。
步骤四:判断用户名是否匹配
代码如下所示:
- #import <Foundation/Foundation.h>
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- // insert code here...
- char name[100];
- NSLog(@"请输入用户名:");
- scanf("%s", name);
- NSString *fileName = [NSString stringWithCString:name encoding:NSASCIIStringEncoding];
- char password[100];
- NSLog(@"请输入密码:");
- scanf("%s", password);
- NSString *filePassword = [NSString stringWithCString:password encoding:NSASCIIStringEncoding];
- NSError *error = [[NSError alloc] init];
- NSString *fileName1 = [NSString stringWithContentsOfFile:@"/users/tarena/desktop/name.txt" encoding:NSUTF8StringEncoding error:&error];
- if ([fileName1 isEqualToString:fileName] == YES)
- {
- NSString *filePassword1 = [NSString stringWithContentsOfFile:@"/users/tarena/desktop/password.txt" encoding:NSUTF8StringEncoding error: &error];
- if ([filePassword1 isEqualToString:filePassword] == YES)
- NSLog(@"登录成功");
- else
- NSLog(@"用户名或密码错误");
- }
- else
- NSLog(@"用户名或密码错误");
- }
- return 0;
- }
上述代码中,以下代码:
- if ([fileName1 isEqualToString:fileName] == YES)
是判断从控制台输入的用户名fileName与从文件中读入的用户名fileName1是否匹配,判断的方法是使用NSString类的isEqualToString方法,该方法有一个实参,是要对比的NSString对象。如果两个对象相同,则返回为真;否则为假。
上述代码中,以下代码:
- NSString *filePassword1 = [NSString stringWithContentsOfFile:@"/users/tarena/desktop/password.txt" encoding:NSUTF8StringEncoding error: &error];
用指定的文件@"/users/tarena/desktop/password.txt"中的内容创建NSString类的对象,从文件中读入的密码放入对象filePassword1。
上述代码中,以下代码:
- if ([filePassword1 isEqualToString:filePassword] == YES)
- NSLog(@"登录成功");
- else
- NSLog(@"用户名或密码错误");
是判断从控制台输入的密码filePassword与从文件中读入的密码filePassword1是否匹配。如果匹配,则在控制台上输出“登录成功”;否则输出“用户名或密码错误”。
3.3 完整代码
本案例的完整代码如下:
- #import <Foundation/Foundation.h>
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- // insert code here...
- char name[100];
- NSLog(@"请输入用户名:");
- scanf("%s", name);
- NSString *fileName = [NSString stringWithCString:name encoding:NSASCIIStringEncoding];
- char password[100];
- NSLog(@"请输入密码:");
- scanf("%s", password);
- NSString *filePassword = [NSString stringWithCString:password encoding:NSASCIIStringEncoding];
- NSError *error = [[NSError alloc] init];
- NSString *fileName1 = [NSString stringWithContentsOfFile:@"/users/tarena/desktop/name.txt" encoding:NSUTF8StringEncoding error:&error];
- if ([fileName1 isEqualToString:fileName] == YES)
- {
- NSString *filePassword1 = [NSString stringWithContentsOfFile:@"/users/tarena/desktop/password.txt" encoding:NSUTF8StringEncoding error:&error];
- if ([filePassword1 isEqualToString:filePassword] == YES)
- NSLog(@"登录成功");
- else
- NSLog(@"用户名或密码错误");
- }
- else
- NSLog(@"用户名或密码错误");
- }
- return 0;
- }
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 步骤
实现此案例需要按照如下步骤进行。
步骤一:从控制台输入某人的身份证号
代码如下所示:
- #import <Foundation/Foundation.h>
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- char id[19] = {};
- NSLog(@"请输入身份证号:");
- scanf("%s", id);
- NSString *idString = [NSString stringWithCString:id encoding:NSASCIIStringEncoding];
- }
- return 0;
- }
步骤二:截取出生日期
代码如下所示:
- #import <Foundation/Foundation.h>
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- char id[19] = {};
- NSLog(@"请输入身份证号:");
- scanf("%s", id);
- NSString *idString = [NSString stringWithCString:id encoding:NSASCIIStringEncoding];
- NSRange birthday = {6, 8};
- NSString *birthdayString = [idString substringWithRange:birthday];
- NSLog(@"出生日期为:%@", birthdayString);
- }
- return 0;
- }
上述代码中,以下代码:
- NSRange birthday = {6, 8};
定义一个范围birthday,在本案例中这个范围的意义是,从身份证号码第7位开始,连续8个数字。程序中是6,因为字符串中的字符从0开始计算,所以到6时是第7位。
上述代码中,以下代码:
- NSString *birthdayString = [idString substringWithRange:birthday];
是截取身份证字符串指定范围内的数字,使用NSString类的substringWithRange方法实现,该方法带有一个实参birthday,是要截取身份证号码从第7位开始,连续8个数字,它们正好是持证人的出生年月日。
步骤三:截取所属省份
代码如下所示:
- #import <Foundation/Foundation.h>
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- char id[19] = {};
- NSLog(@"请输入身份证号:");
- scanf("%s", id);
- NSString *idString = [NSString stringWithCString:id encoding:NSASCIIStringEncoding];
- NSRange birthday = {6, 8};
- NSString *birthdayString = [idString substringWithRange:birthday];
- NSLog(@"出生日期为:%@", birthdayString);
- NSString *idData[][2] = {
- {@"北京", @"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"}
- };
- NSString *city = [idString substringToIndex:2];
- for (int i = 0; i < 5; i++)
- {
- NSString *idCity = idData[i][1];
- if ([city isEqualToString:idCity] == YES)
- {
- NSLog(@"所属省份为:%@", idData[i][0]);
- break;
- }
- }
- }
- return 0;
- }
上述代码中,以下代码:
- NSString *idData[][2] = {
- {@"北京", @"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"}
- };
使用一个二维数组,建立省份名与代码之间的联系。
上述代码中,以下代码:
- NSString *city = [idString substringToIndex:2];
是从身份证字符串中截取前两位地址码,使用NSString类的substringToIndex方法实现,该方法带有一个实参,表示截取从字符串第一个字符到该实参之间所有字符,形成一个新的字符串。
上述代码中,以下代码:
- for (int i = 0; i < 34; i++)
- {
- NSString *idCity = idData[i][1];
- if ([city isEqualToString:idCity] == YES)
- {
- NSLog(@"所属省份为:%@", idData[i][0]);
- break;
- }
- }
使用一个循环遍历数组,查找身份证上的地址码对应的省份名称。以下代码:
- NSString *idCity = idData[i][1];
首先从数组中读取一个地址码。以下代码:
- if ([city isEqualToString:idCity] == YES)
判断该地址码与从身份证上截取的地址码是否相同,如果相同,则在控制台上输出该地址码对应的省份名称并结束遍历数组;否则继续遍历数组。
4.4 完整代码
本案例的完整代码如下:
- #import <Foundation/Foundation.h>
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- char id[19] = {};
- NSLog(@"请输入身份证号:");
- scanf("%s", id);
- NSString *idString = [NSString stringWithCString:id encoding:NSASCIIStringEncoding];
- NSRange birthday = {6, 8};
- NSString *birthdayString = [idString substringWithRange:birthday];
- NSLog(@"出生日期为:%@", birthdayString);
- NSString *idData[][2] = {
- {@"北京", @"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"}
- };
- NSString *city = [idString substringToIndex:2];
- for (int i = 0; i < 34; i++)
- {
- NSString *idCity = idData[i][1];
- if ([city isEqualToString:idCity] == YES)
- {
- NSLog(@"所属省份为:%@", idData[i][0]);
- break;
- }
- }
- }
- return 0;
- }