Objective-C & Sprite Kit太空历险记 : 2. 初级训练营——Objective-C基础(上)

来源:互联网 发布:333什么意思网络用语 编辑:程序博客网 时间:2024/04/30 03:13
     原文

  http://www.ituring.com.cn/article/211360   

 

本部分训练的教官是O-C军士,训练科目是Objective-C编程的基础知识,主要内容包括:

  • 代码文件
  • 注释
  • 变量
  • 常量
  • 整数
  • 浮点数
  • 布尔类型
  • 字符
  • 自定义函数
  • 块(block)
  • 指针
  • 异常处理
  • 枚举
  • 结构
  • 预处理

这么多内容?!亲!您能慢慢来吗~

O-C教官来了,训练马上开始!还没冲咖啡?怕是来不及了!

O-C教官:各位好!来到这里,相信你已经下定决心了,不过,想成为一名真正的“OC & SK舰队”队员,我们还需要很多科目的训练,会很坚苦,也会很有趣。如果你在学校参加过C语言夏令营,可能对本部分训练中的大部分内容比较熟悉,不过,请不要骄傲;而没有参加过C语言夏令营也不需要难道,因为这和真正的战斗训练并没有必然的联系。下面,我们马上开始第一个课目。

2.1. 代码文件

O-C教官的排场还真不小,上课时后面还跟着几个圆乎乎的机器人,大家看,它们排着队晃晃悠悠就来了。

看上去都一样,一定是一个型号的机器人吧。是的,听说都是TEXT型的!

还好,肚皮上有编号,不然怎么认得出来呀。对了,为什么编号都有个小圆点呢?总不会是那啥吧?!

笑哭中~,亲!您也不是第一天用电脑了,那叫扩展名!不同的扩展名表示不同的文件类型。

哦~,那这几种文件类型是怎么回事!

O-C教官说话了,大家严肃点!这是在Objective-C项目中常见的几种源代码文件类型,下面会一个个点名。

首先让.h出列,谁让它是头(header,如果你喜欢,可以加儿音)文件呢。那头文件的功能是什么呢?和C/C++相似,在Objective-C中,头文件的作用就是声明一系列可以供其它代码文件使用的资源,如函数、全局变量、类的接口部分等等。请注意,在头文件里只负责声明一下,就当是Mark一下,刷一下存在感,而不是资源真正的定义,那定义的东西都放哪呢?

请.m文件出列,这是模块(module)文件。是的,真正的定义部分都放在.m文件中,这包括函数的定义、全局变量的定义、类的实现等等 。

深呼吸,下面继续!

.c文件,C语言源代码文件,在Objective-C项目中,我们也可以编写纯纯的C语言代码,此时,你应该使用.c文件。请注意,.c文件的角色与.m的角色相似,经常需要与头文件一起使用。

.cpp文件,C++源代码文件,相信大家了解这斯也不是一件难事,是的,在Objective-C中,我们同样可以编写C plus plus代码,所说它也是面向对象的。

.swift文件,这只鸟看着挺眼熟。是的,这就是Swift源代码文件。Swift是另一种来自苹果宇宙的编程语言。此外,听说一只小Swift正在四处漂泊,也许作者会带着大家了解它的故事,一起期待吧!^_^

“马上进入Xcode中自己的实习岗位!要快!接下来是实际操作科目!”O-C教官说的,不是我说的哈! 继续OCDemo项目,在Xcode菜单中,通过"File"->"New"->"File"项创建一个头文件(Header File),并全名为FileTypeDemo.h,如下图:

修改这个文件的内容如下,你可以把穿着绿色马甲的部分删除掉,当外,也可以修改为自己想说的话,哪个星球的语言就不重要了,只是要记得使用//作为行的开头,而且习惯上还会加一个空格。

#ifndef __FileTypeDemo_h__#define __FileTypeDemo_h__extern int gCounter;void gCounterAdd();#endif

这么多#符号是什么情况?我们称之为预处理指令。

预处理,就是预先处理?是的,只不过这些工作由编译器来完成,我们只要正确书写就行了。那怎么正确书写呢?这个也不难,基本的要求就是:#符号别忘了、字母拼对了,最后就不要加分号了。

接下来,我们先从字面上了解这些指令的功能吧。

#ifndef和#endif指令的功能是,如果没有定义__FileTypeDemo_h__宏(#define指令定义,稍后说明),则执行#ifndef和#endif指令之间的内容。默认情况下,Xcode中会自动使用“项目名称+头文件名”的格式来定义宏,我们可以使用默认的宏名称,也可以根据项目约定进行相应的修改。

#define指令用于定义宏,这是货真价实的符号;而且,在定义宏的同时也可以定义它表示的值,如:

#define MaxLength 99

本例中,编译器开工时,会在代码中使用99替换所有MaxLength标识;而这也是宏的基本功能之一。在后续的科目中,我们会看到更多关于宏的应用。

再来看两个声明语句(都说了头文件中只是声明了^_^):

extern int gCounter;void gCounterAdd();

第一条语句声明了一个整数(int)类型的变量gCounter,其中的extern关键字说明此变量是定义在另外的文件中,第二条语句声明了一个函数gCounterAdd()。请注意,它们都是单个语句,会以分号作为结束。此外,我不会告诉你它们是定义在FileTypeDemo.m文件里的。

接下来,通过Xcode菜单"File"->"New"->"File",创建一个Objective-C文件(Objectie-C File),并命名为FileTypeDemo.m,如下图所示。

然后,修改FileTypeDemo.m文件的内容如下面的代码。

#import "FileTypeDemo.h"int gCounter = 0;void gCounterAdd(){    gCounter++;}

最后,我们在main()函数中(main.m文件)使用它们,如下面的代码。

#import <Foundation/Foundation.h>#import "FileTypeDemo.h"int main(int argc, const char *argv[]){    @autoreleasepool {        NSLog(@"%i\n", gCounter);        gCounterAdd();        NSLog(@"%i", gCounter);    }    return 0;}

代码执行后,会显示0和1。

本科目演练完毕,通过这部分的练习,我们应该了解.h和.m文件是如何配合使用的,为我们进行下一步更复杂的科目练习做好准备。

2.2. 注释

这位仁兄是?好像很生气的样子。的确,他就是注释机器人先生,要知道,我们前面的训练中都会把注释删除,难怪它会生气。

不是说注释不影响代码的执行吗?代码中没有注释问题也不大吧?

O-C教官说话了:恐怕不是这样,在代码中添加注释是一项非常重要的工作,虽然我们常说,对代码最好的解释就是代码本身,但是,对于复杂的代码来讲,能通过注释简单地说明一下代码的目的也是一个不错的选择。 在Objective-C项目中,我们可以使用两种注释方法:

  • 块注释,即将注释内容放在/  /之间。 
  • 行注释,使用//开始,一直到本行的结束都当作注释内容。

如下面的内容。

/*     这里块注释内容*/// 这里是行注释内容

这看上去也是很简单的吗?是的,注释本身并没有什么特别之处,重要的是在代码中如何应用。一般来讲,注释会用于说明代码的目的,或者是算法和思路的简单说明,而不是对于代码的重复;另一方面,使用一行空注释,还可以有效地对代码块进行分割,便于阅读代码。

大家可以在实践中逐步理解注释的使用特点,并在项目中合理地、有效地添加注释。

2.3. 变量

O-C教官:接下来的科目,我们需要处理具体的数据了,比如,太空船在什么位置,其坐标就需要使用数字来表示(最少在地球上是这么干的)。只是在代码中,你不可能让数字满天飞吧,此时,你可以使用标识符来表示数据,这样,在代码中,你就可以明确地知道数字的含义了。

变量就是一种标识符,用于标识数据项,它的值可以根据程序的需要而改变。

变量的主要特性包括名称、类型和值,当然还包括它们的使用范围,不过,本章我们主要讨论它的基本特性,即类型、值和数据的基本运算。

在Objective-C代码中,声明一个变量的基本方法是通过如下格式的语句。

<数据类型> <变量名称>;

<数据类型>指定了变量中数据的类型,如整数、浮点数等,不明白,没关系,稍后我们会有数据类型相关的训练科目。

<变量名称>就是变量的标识符,习惯上,我们使用首字母小写,然后每个单词首字母大写的形式,如index、counter、xPosition。请注意,在给变量命名时,应尽量使用有意义的名称;不过,有时候也会有一些习惯用法,我们会在后续的训练当中看到。

使用变量时,应该首先确定它的值;比如,在定义变量时,可以同时指定变量的值(只要不是在头文件中),如下面的代码:

int num = 1;

这个代码的作用就是声明一个整数变量num,并将其值定义为1。其中的等号(=)称为赋值运算符,它的作用是将运算符右边的数据赋值到左边的变量或其它类型的标识符中。

此外,我们还可以先声明,后赋值,如下面的代码。

int num;num = 1;

O-C教官说了:队员们,太空旅行非常危险,应随时注意太空船和小行星的位置,掌握确实的数据,否则一不小心就会……,毕竟太空船上不只有机器人。

2.4. 常量

报告长官,我们的确需要时刻关注太空船的位置,但是不是有些数据就不需要总盯着呀?比如计算球形天体或圆形轨道相关数据时,圆周率是不变的!

O-C教官:是的,如果不考虑引力造成的时空弯曲,这个理论是成立的;在Objective-C引力范围内,圆周率使用M_PI标识,它定义为一个宏,不过,我们更习惯称之为常量。

常量,是指在程序运行过程中不会改变的量,常常用来指定一些常数或特殊数值。在Objective-C中,我们可以使用const关键字定义一个真正的常量,如下面的代码。

#import <Foundation/Foundation.h>const int MaxAge = 150;int main(int argc, const char *argv[]){    @autoreleasepool {        NSLog(@"%i", MaxAge);    }    return 0;}

另一种创建常量的方法是通过#define指令定义宏来模拟常量的使用,如下面的代码。

#import <Foundation/Foundation.h>#define MaxLength 100int main(int argc, const char *argv[]){    @autoreleasepool {        NSLog(@"%i", MaxLength);    }    return 0;}

代码会显示100。

关于宏的命名,传统的C风格是使用字母全大写,每个单词使用下划线分隔,如前面提到的M_PI;而本书中,自定义的常量会使用每个单词首字母大写的风格,如MaxLength。

在代码中使用常量有两个基本的好处,一是当我们需要修改这个数值时,只在定义的地方修改一次就可以了,而不是在代码中所有使用它的地方修改(那会是一场恶梦);第二个好处就是,使用一个有意义的名称来标识数据,可以避免可能的输入错误,要知道,在太空中,如果你写错一点点数据,就有可能掉入黑洞,谁知道那里面是什么情况呀。

2.5. 整数

报告长官,我练习时发现了一个问题,输入的数据并没错,但执行的结果总是不对,是不是系统有问题呀?

O-C教官:让我看看你的代码。

int xPos;xPos = 105.5;NSLog(@"%i", xPos);

明明写的是105.5,怎么就总是显示105呢?

O-C教官:你还明明把xPos变量声明为整数(int)呢?

原来int类型不能处理小数呀!不过,这也不能怪我们,教官你一直都在用int定义变量,谁知道它不能处理小数呢?

O-C教官:好吧,那现在就给大家介绍数据的类型吧。

在Objective-C中,数据类型可以分为两种风格和若干种类型,我们分别介绍。其中,两种风格是指:

  • C风格的基本类型,如int、unsingned int、long int、float、double、char等,这些类型与C语言中的数据类型应用是相同的。
  • Foundation框架中的数据类型,如NSInteger、NSUInteger、NSString、CGFloat等。Foundation是在iOS和OS X系统中进行开发的基本框架,在这个框架中,定义了一系列的数据类型;如果我们是在使用Foundation框架进行开发,可以考虑尽量使用这一类的数据类型。

接下来是真正的数据类型,如整数、浮点数、布尔和字符类型,我们会讨论它们的取值范围、运算、类型转换等应该特性;并且,我们还会讨论C数据类型和Foundation数据类型的区别和应用特点比较。首先,我们从整数开始。

2.5.1. 取值范围

O-C教官:整数用于处理没有小数部分的数据,按照计算机的内部处理方式又分为有符号整数和无符号整数。其中,有符号整数可以处理负数、零和正数,而无符号整数只能处理零和正数。

在C数据类型中,int和unsigned int比较常用的两种整数类型。其中,int是有符号整数(singn int)的简写形式,而unsigned int则是无符号整数。它们定义为32位整数,int类型的取值范围就是-2147483648到2147483647之间,即-231到231-1之间;相应的,unsigned int的取值范围则是0到232-1之间。

在Foundation框架中,常用的整数类型为NSInteger和NSUInteger,如果我们呼叫支援,看一看它们的定义就会发现,这些类型实际使用了typeof关键字定义为C数据类型的别名,在64位环境下,它们分别定义为long和unsinged long,而在32位环境下,它们定义为int和unsinged int类型。为了保证数据类型的平台兼容性,建议大家在项目中使用NSInteger和NSUInteger类型名。此外,我们应该知道,iOS和OS X系统都已进入了64位时代;所以,在使用新的开发工具(如Xcode)或在开发较新平台下的项目时,我们可以认为NSInteger和NSUInteger类型分别是long int和unsigned long int类型的。

在Foundation框架中,这些常用的数据类型都定义为C数据类型的别名,在后续的训练课目中,我们还可以看到更多的类型。

2.5.2. 算术运算

报告长官,1号机库有30架战斗机,2号机库有29库战斗机,一共有多少架战斗机,在程序中应该怎么写?

O-C教官:用加法(+),如下面的代码。

NSInteger hangar1 = 30;NSInteger hangar2 = 29;NSInteger sum = hangar1 + hangar2;NSLog(@"共有%li架战斗机", sum);

要是飞走了16架,还剩多少架,什么计算呢?

O-C教官(狂汗~):用减法(-)呀,亲!接着上面的代码写。

NSInteger overplus = sum - 16;NSLog(@"剩余%li架战斗机", overplus);

一个飞行中队有4架战斗机,那14个中队有多少架呢?

等等,我知道,用乘法(*),小学生都会,呵呵。

NSInteger squadrons = 14;sum = squadrons * 4;NSLog(@"14个中队共%li架战斗机", sum);

那2号机库里有几个飞行中队呢?用除法(/),如:

squadrons = hangar2 / 4;NSLog(@"2号机库有%li个飞行中队", squadrons);

好像2号机库里的战斗机数量不能被4整除,分了7个中队,还剩几架战斗机,这个怎么计算呢?

O-C教官:在这里,可以直接使用取余运算符(%)来计算,如下面的代码。

NSInteger remainder = hangar2 % 4;NSLog(@"2号机库分完飞行中队还剩%li架战斗机", remainder);

请注意,在任何编程语言中,运算符都会有一定的优先级,即一系列运算符在表达式中运算的先后顺序,如果你不能保证百分之百的记忆正确,建议使用一对小括号()来强制指定运算顺序,这样会更安全。

2.5.3. NSLog()函数与格式化输出

前面,我们已经多次使用NSLog()函数显示信息了,在开发和调试过程中,我们可以使用它显示各种信息,当然,最终结果都是文本的,而其它类型的数据则需要使用格式化字符,常用的整数的格式化字符包括:

  • int类型使用“%i”格式化字符,我们还可以使用“%x”将整数显示为十六进制,使用“%o”将整数显示为八进制。
  • unsigned int类型,无符号整数,使用“%u”格式化字符。
  • long int类型,长整型数据,使用“%li”格式化字符。
  • unsigned long int类型,无符号长整型数据,使用“%lu”格式化字符。
  • long long int类型,长长整型数据,使用“%lli”格式化字符。
  • unsigned long long int类型,无符号长长整型数据,使用“%llu”格式化字符。

这些整数类型也都有相应的十六进制和八进制的格式化字符,基本变化原则就是将列表中给出的格式化字符中的i或u变为x或o。

2.5.4. 复合赋值运算

在这里,复合赋值运算是指将算术运算和赋值运算合并,如下面的代码。

NSInteger i = 1;i += 2; // 相当于 i = i + 2NSLog(@"%li", i);

在Objective-C中,五种算术运算都有相对应的复合赋值运算符,即:+=、-+、*=、/=和%=运算符。

2.5.5. 增量与减量运算

在整数的操作中,还有一种运算很常用,那就是增量计算,简单的说就是进行加1计算;而这个计算又包括两种:前增量和后增量。

前增量,表达式的值和变量的值都是变量原值加1,即首先进行加1操作,然后表达式才返回结果。如下面的代码。

int i = 1;NSLog(@"%i", ++i);     // 2NSLog(@"%i", i);       // 2

后增量,表达式的值会是变量的原值,即表达式先返回结果,再进行变量加1的操作。如下面的代码。

int i = 1;NSLog(@"%i", i++);    // 1NSLog(@"%i", i);      // 2

如果我们只需要使用计算后的变量值,则前增量和后增量的区别就无所谓了,但是,如果我们需要使用增量运算表达式的值,就必须非常小心前增量和后增量运算的区别。

与增量运算相对应的减量运算,同样包括前减量和后减量运算,工作方式与增量运算相似,只是减量运算执行的是减1操作。

2.5.6. 二进制与位运算

本部分是初级训练中的可选科目,可能也是本书中为数不多的与计算机基本工作原理相关的内容;了解一下不会有坏处,说不定还能给考试加分,当然,现在不研究,以后有需要也可以随时回来串串门。

了解整数相关的位运算,我们首先需要了解整数在计算机中的处理方式,也就是整数的二进制形式;前面,我们说过的32位整数、64位整数,就指的是二进制位。在二进制位中,数值只包括0和1。

无符号整数的二进制形式

无论是8位还是64位,它们对于整数处理的基本原理是一样的,所以,接下来,我们就使用简单点的8位二进制形式来讨论相关的应用问题。

二进制如何转换为整数呢?我们先来看0和正数(包括无符号整数及有符号整数中的正数)的转换方法。如果二进制位上是1,就使用2 n -1计算出整数,其中,n是从右向左数的第几位;然后,将所有的数值相加,就得到了这个二进制数所表示的十进制整数。 

如图中的00011001,我们可以得到算式:2 4 +2 3 +2 0 =16+8+1=25,最终,我们计算出二进制数00011001表示的整数就是25。 

那么,正整数如何转换为二进制呢?我们还以25为例,如下图所示的计算方法。

首先,我们使用25除2,商是12,余数为1;然后使用12除2,商是6,余数是0;以此类推,直到商为1时结束计算。然后,我们从下到上写,即11001,如果位数不够,则在前面补0,如我们需要8位二进制数,就是00011001。

逻辑位运算

下面,我们了解一下Objective-C中的位运算符,它们包括:

按位与运算,使用&运算符。两个运算数都是1时,结果为1,否则为0。如下图。

按位或运算,使用|运算符。当两个数有一个为1时,结果为1,只有两个数都是0时,结果才为0。如下图。

按位异或运算,^运算符。当两个数一样时,结果为0,只是两个数不一样时,结果才为1。如下图。

按位取反运算,!运算符。即1变0,0变1。如下图。

补码

一个二进制数的补码是指其按位取反后加1的值。还以00011001为例,其按位取反的结果是11100110,再加1就是11100111。这样,11100111就是00011001的补码。

那么,在计算机中使用补码有什么用呢?我们在有符号整数的处理中就可以看到了。

有符号整数的二进制形式

我们知道,有符号整数可以处理负数、零和正数,那么,使用二进制的情况下,如何处理整数的符号呢?答案是,有符号整数的二进制最高位就是它的符号位,如下图所示。

当有符号整数为零或正数时,符号位为0,也就是说,8位有符号整数的最大取值就是01111111,我不会告诉你这就是127的。

负数的表示就有点意思了,除了符号位为1,其它位上的数据实际上是负数绝对值的补码形式。比如,-128的二进制就是10000000(这可不是-0)。我们先看128的二制形式,即10000000,请注意,此时,我们不考虑符号问题;然后,按位取反就是01111111,再1得到补码10000000(和原数一样一样的^_^)。 不过,我们现在处理的是8位有符号整数,所以,只有后7位才是真正的数据,所以,128补码中的最高位1就直接扔掉了(在计算机中就是这么绝),然后换一个1,只不过其含义是负数;这样,-128的二进制就是10000000。

那么,为什么负数要使用补码呢?原因是,在计算机内部,有符号整数可以只进行加法操作,而不需要减法操作,真是多一事不如少一事。下面,我们来看看25-25在计算机中的二进制处理。

首先,25-25可以处理为25+(-25),好的,25的二进制形式是0011001(不含符号位),那么,-25呢?先是25取反得1100110(不含符号位),再加1得到补码1100111。最后就是两个二进制数的相加(含符号位),如下图所示。

好的,我们正在处理的是8位有符号整数,所以,最终的结果只有00000000,也就是整数0。

现在,大家应该了解有符号整数和符号整数的取值范围是怎么确定的吧!如果你感兴趣,可以按二进制计算一下试试,只是注意别加错了。^_^

位移运算

O-C教官:关于二进制,我们最后讨论一下有符号整数与无符号整数的位移运算。

在Objective-C中,位移运算包括位左移运算(<<运算符)和位右移运算(>>运算符),对于这两种位移运算,我们同样按有符号和无符号整数分别讨论。

首先是无符号的位移操作,这种操作很简单,我们8位无符号整数64为例,它的二进制表示为01000000,那么它右移2位的操作就如下图所示。

我们可以看到,当一个无符号整数右移操作时,会将低的数据直接舍弃,然后在高位补零。那么,64右移2位后的二进制就是00010000,我们换算成十进制就是16。实际上,我们可以看到,当一个整数(N)进行右移n位时,就是在进行N÷2 n 的计算。 

反过来,当我们进行整数(N)的左移运算时,高位数据舍弃,在低位补0;实际上,就是在进行N×2 n 的计算。但请注意,当我们进行整数的位移运算时,应考虑整数的取值范围;如果左移超出了允许的最高位,也就是超出了整数的取值范围,同样会舍弃,这时就会造成整数的溢出。 下面的代码演示了无符号整数的位移运算: 

NSLog(@"%ul", 64 >> 2);  // 16NSLog(@"%ul", 16 << 2);  // 64

对于有符号整数的位移运算,会有些不同。如进行8位有符号整数-64的右移运算,我们知道,-64的二进制表示为11000000,那么,它的右移两位计算操作就如下图所示。

我们可以看到,在对有符号整数进行移位操作时,只对数据位进行移动,而符号位保持不变;如图中的右移操作,会在数据的高位补上与符号位相同的数据,这样,-64右移2位后的二进制数就是11110000,也就是-16。我们可以看到,这也是在N÷2 n 进行的操作。 

对于有符号整数的左移操作,同样是只移动数据位,保持符号位不变,然后,在低位补0,这实际上也是执行的N×2 n 操作。 

下面的代码演示了有符号整数的位移运算:

NSLog(@"%ul", -64 >> 2);  // -16NSLog(@"%ul", -16 << 2);  // -64

2.6. 浮点数

O-C教官:现在是绕星飞行模拟训练,我们将要进入Planet-I行星的圆形轨道,现在我们距离行星的中心是1万公里,那么,轨道的周长是多少呢?

报告教官,1万公里是轨道的半径,那么,轨道周长就是1×2×π万公里。

O-C教官:请写出代码,你们必须适应使用控制系统来操作太空船。

报告教官,听说π后面的小数位很多,在计算机中,我们如何处理呢?

O-C教官:那就先说说浮点数吧。

软件开发中,另一种基本的数据类型就是浮点型数据,它用于处理包含小数部分的数据;在Objective-C中,常用的浮点数类型包括float和double。

float称为单精度浮点数,在NSLog()函数中的格式化字符为“%f”,我们还可以使用特殊的格式显示浮点数,如使用“%e”会以科学记数法显示浮点数。

double称为双精度浮点数,其处理数据范围更大,在NSLog()函数中的格式化字符为“%Lf”。

在Foundation框架中,同样定义了浮点数类型的别名,如CGFloat的64位平台下定义为double类型的别名,而在32位环境下定义为float类型的别名。

开发过程中,可能经常需要在整数和浮点数类型之间进行转换,接下来,我们就以int和float类型为例讨论整数与浮点数之间的转换问题。

首先,从int类型到float类型的转换是没有任何问题的,直接赋值就可以了,如下面的代码:

int intNum = 100;float floatNum = intNum;

代码中,整数实际上是隐式地转换为浮点数,因为float类型比int类型的取值范围大,所以,这种隐式地转换是没有问题的。

反过来,当我们需要将float类型转换为int类型时就要注意了,主要包括两个问题:一是小数部分会丢失,相信这一点并不难理解,因为整数不能保存小数部分,所以丢失是必然的了。

浮点数类型计算时,可以使用加法、减法、乘法和除法算术运算符。在这些运算中,如果混合有浮点数和整数,会自动将整数转换为浮点以后计算,计算结果同样为浮点数。对于取余运算,则会将浮点数自动转换为整数后计算。

另外一个问题是如何处理丢失的小数部分。默认情况下,浮点数在转换成整数时,会直接舍弃小数部分;不过,我们也可以自己决定如何操作,如使用以下几个函数来处理这个问题。

  • floorf()函数,舍去参数中的小数部分,只返回整数部分,请注意,此函数的参数和返回结果都是float类型,如果需要整数类型,还是需要进行转换操作。如果操作double类型,则使用floor()函数。
  • ceilf()函数,舍去参数中的小数部分,整数部分加1,此函数的参数和返回值同样为float类型;相应的操作double类型的函数是ceil()。

最后,别忘了本节开始的训练题目,计算Planet-I行星的圆形轨道周长,下面的代码就是了:

CGFloat circumference = 1*2*M_PI;NSLog(@"圆形轨道周长约为 %Lf 万公里", circumference);
0 0