Objective-C-2.0程序设计-第13章-基本的C语言特性.ppt_第1页
Objective-C-2.0程序设计-第13章-基本的C语言特性.ppt_第2页
Objective-C-2.0程序设计-第13章-基本的C语言特性.ppt_第3页
Objective-C-2.0程序设计-第13章-基本的C语言特性.ppt_第4页
Objective-C-2.0程序设计-第13章-基本的C语言特性.ppt_第5页
免费预览已结束,剩余112页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第13章基本的C语言特性 目录 13 1数组13 2函数13 3结构13 4指针13 5联合13 6他们不是对象13 7其他语言特性13 8工作原理 13 1数组 Objective C提供了一项功能 它允许用户义一组有序的数据项 即数组 在Objective C中 可以定义一个名为grades的数组 它代表的不是一个成绩值 而是一组成绩值 然后通过名为索引或下标的数字来引用其中各个元素 x数组中的第i个元素表示为x i grades 5 名为grades的数组中索引为5的元素数组元素以0索引开头 grades 0 grades数组中第一个元素 13 1数组 任何一个数组元素都可以用在可用常规变量的地方 g grades i 以上表达式使用索引为i的grades数组元素的值 并将它赋给变量ggrades 100 95将数值95存储到grades数组中索引为100的元素中 13 1数组 改变数组下标的变量值 可以浏览数组中的元素for i 0 i 100 i sum grades i 依次浏览数组grades的前100个元素 元素0 99 并将每个成绩相加之和赋给变量sum for循环结束之后 遍历sum包含数组grades的前100个元素值之和 13 1数组 在使用数组之前必须先声明数组 数组的声明涉及声明数组所包含元素的数值类型 如int float或者对象 以及将存储在数组中的最大元素数目 Fraction fracts 100 声明fracts为包含100个分数的数组 通过使用下表0 99 可以有效的引用该数组的元素 fracts 2 fracts 0 add fracts 1 调用Fraction类的add 方法 将数组fracts的前两个分数相加 并将结果存储到数组第三个位置 13 1数组 代码清单13 1产生斐波那契数的前15个值列表 尝试预测输出结果 前两个斐波那契数 我们称之为F0和F1 分别定义为0和1 此后的每个斐波那契数Fi都定义为前两个斐波那契数Fi 2和Fi 1 程序通过计算Fibonacci 0 和Fibonacci 1 之和 就可以直接计算出Fibonacci 2 这个计算公式是在for循环中执行的 它计算出F2到F14的值 13 1数组 Program13 1 Programtogeneratethefirst15 Fibonaccinumbers importintmain intargc char argv NSAutoreleasePool pool NSAutoreleasePoolalloc init intFibonacci 15 i Fibonacci 0 0 bydefinition Fibonacci 1 1 ditto for i 2 i 15 i Fibonacci i Fibonacci i 2 Fibonacci i 1 for i 0 i 15 i NSLog i Fibonacci i pooldrain return0 Program13 1Output01123581321345589144233377 13 1 1数组元素的初始化 在变量申明时可以给它赋初值 也可以给数组元素赋初值 通过简单的列出数组元素的初值 并以第一个元素开始 就可以实现 列表中的值由逗号隔开 并且整个列表放于一对大括号之内 intintegers 5 0 1 2 3 4 将0赋给integers 0 1赋给integers 1 2赋给integers 2 依此类推 字符数组以同样的方式初始化 所以表达式charletters 5 a h c d e 定义了字符数组letters 并将5个元素分别初始化为字符 a b c d 和 e 13 1 1数组元素的初始化 不必完全初始化整个数组 比如 floatsample 500 100 0 200 0 500 5 前三个元素被初始化为100 0 200 0 500 5而其余497个元素被设为0 通过将元素编号放在大括号内可以任意顺序的初始化指定的数组元素 比如 intx 1233 inta 9 x 1 2 3 1 2 0 1 定义了一个名为a的10个元素数组 根据数组中最大索引得出的 并将数组的最后一个元素初始化为x 1 1234 此外 它的前3个元素分别被初始化为1 2和3 13 1 2字符数组 代码清单13 2的目的是阐明如何使用字符数组 Program13 2 importintmain intargc char argv NSAutoreleasePool pool NSAutoreleasePoolalloc init charword H e l l o inti for i 0 i 6 i NSLog c word i pooldrain return0 Program13 2OutputHello 13 1 2字符数组 字符数组word的声明没有指出数组中的元素个数 Objective C语言允许定义没有指明元素个数的数组 如果是这样定义的 则自动根据初始化元素的数目确定该数组大小 如果在字符数组结尾添加一个终止空字符 0 就产生了一个通常称为字符串的变量 charword H e l l o 0 NSLog s word 格式字符告诉printf持续显示字符直到到达终止空字符 也就是在word数组最后添加的字符 所以该语句没有问题 13 1 3多维数组 二维数组最自然的应用之一是矩阵 考虑下面的4x5矩阵 105 317829008 73220101400876数学中 通过双下标来引用矩阵中的元素 如果将上面的矩阵命名为M 符号Mi j则代表在第i行第j列的元素 i的范围从1到4 j的范围从1到5 Objective C语言中 引用二维数组的元素时类似 但是Objective C语言从0开始计数 所以矩阵的第一行实际上是0行 而第一列是0列 13 1 3多维数组 在数学上使用符号Mi j 而Ojective C语言中使用等价的符号M i j 第一个索引指的是行数 第二个索引指的是列数 定义二维数组的方式和一维数组的相同 intM 4 5 声明M为4行5列的二维数组 总共包含20个元素 数组中的每个位置都包含整型值 13 1 3多维数组 初始化二维数组的方法类似于一维等价数组的初始化方式 列出初始化元素时 它们的值是根据行排列的 大括号对用来分隔初始化的各行 因此 要将数组M定义和初始化为前面表中列出的元素 可以使用下面的表达式 intM 4 5 10 5 3 17 82 9 0 0 8 7 32 20 1 0 14 0 0 8 7 6 13 1 3多维数组 除了最后一行 毎行结束的大括号之后必须加上逗号 内层括号可以省略 如果没有内层括号 将按行进行初始化 intM 4 5 10 5 3 17 82 9 0 0 8 7 32 20 1 0 14 0 0 8 7 6 不必初始化整个二维数组 未被初始化的值都设为0 此时需要花括号对 以强制正确的初始化 intM 4 5 10 5 3 9 0 0 32 20 1 0 0 8 13 2函数 每个程序中接触到的NSLog例程就是一个函数例子 事实上 每个程序还用到一个名为main的函数 回顾你编写的第一个程序 代码淸单2 1 它在终端显示 programmingisfun 这个短语 importintmain intargc char argv NSAutoreleasePool pool NSAutoreleasePoolalloc init NSLog Programmingisfun pooldrain return0 13 2函数 下面是名为printMessage的函数 它产生同样的结果 函数printMessage和代码清单2 1main函数的唯一区别在第一行 第一行函数定义告诉编译器关于该函数的4件事情 谁可以调用这个函数函数的返回值类型函数的名称函数使用的参数数目和类型 voidprintMessage void NSLog Programmingisfun 13 2函数 函数printMessage的第一行告诉编译器printMessage是这个函数的名称 并且该函数不返回任何值 第一个void关键字的用途 与方法不同 不必将函数的返回值类型放在一对圆括号中 第二个void关键字的用途说明该函数没有任何参数 在Objective C系统中 main是一个特别的名称 它是指示程序开始运行的位置 每个程序都必须有一个main函数 13 2函数 向前面的代码添加一个main函数 以完成这个程序 如代码凊单13 3所示 Program13 3 importvoidprintMessage void NSLog Programmingisfun intmain intargc char argv NSAutoreleasePool pool NSAutoreleasePoolalloc init printMessage pooldrain return0 Program13 3OutputProgrammingisfun 13 2函数 代码清单13 3包含两个函数 printMessage和main因为printMessage不带有参数 所以可以简单地在名称后面添加一对左右圆括号来调用它 13 2 1参数和局部变量 通过该函数的一个参数 指要计算哪个三角数 然后这个函数计算出所求的数值并显示结果 代码清单13 4显示了完成这项任务的函数和测试它的main例程 Program13 4 import FunctiontocalculatethenthtriangularnumbervoidcalculateTriangularNumber intn inti triangularNumber 0 for i 1 i n i triangularNumber i NSLog Triangularnumber iis i n triangularNumber 13 2 1参数和局部变量 intmain intargc char argv NSAutoreleasePool pool NSAutoreleasePoolalloc init calculateTriangularNumber 10 calculateTriangularNumber 20 calculateTriangularNumber 50 pooldrain return0 Program13 4OutputTriangularnumber10is55Triangularnumber20is210Triangularnumber50is1275 13 2 1参数和局部变量 函数calculateTriangularNumber的第一行是voidcalculateTriangularNumber intn 它告知编译器calculateTriangularNumber是一个函数 不返回任何值 关键字void 并且带有一个名为n的int参数 不能像编写方法那样 将参数类型放在圆括号中 因为要计算第n个三角数 所以必须设置一个变量 以便在计算过裎中储存三角数的值 TriangularNumber 还需要一个变量作为循环的索引 i 13 2 1参数和局部变量 函数中局部变量的行为同方法中的一样 如果在函数内给变量赋予初始值 那么每次调用该函数时 都会指定相同的初始值 在函数中 和在方法中一样 定义的变量称为自动局部变量 因为每次调用该函数时 它们都自动 创建 井且它们的值对于函数来说是局部的 静态局部变量用关键字static声明 它们的值在函数调用的过程中保留下来 并且初始值默认为0 局部变量的值只能在定义该变量的函数中访问 它的值不能从函数之外访问 13 2 1参数和局部变量 在main函数中 数值10是在第一次调用函数calculateTriangularNumber时作为参数传递的 然后 执行直接转换到该函数 数值10成为函数中形参n的值 然后 该函数计算出第10个三角数的值并显示结果 再次调用函数calculateTriangularNumber时 传递参数20 经过与前面描述相似的过程 该数值成为函数中n值 然后 该函数计算出第20个三角数的值并显示答案 13 2 2函数的返回结果 和方法一样 函数也可以返回值 Return语句返回的值类型必须和函数声明的返回类型一致 floatkmh to mph floatkm speed 定义了函数kmh to mph 它使用一个名为km speed的float参数 并返回浮点型小数 13 2 2函数的返回结果 代码清单13 5使用函数重新编写代码清单5 7中求最大公约数的算法 Program13 5 import Thisfunctionfindsthegreatestcommondivisoroftwo nonnegativeintegervaluesandreturnstheresultintgcd intu intv inttemp while v 0 temp u v u v v temp returnu 13 2 2函数的返回结果 main NSAutoreleasePool pool NSAutoreleasePoolalloc init intresult result gcd 150 35 NSLog Thegcdof150and35is i result result gcd 1026 405 NSLog Thegcdof1026and405is i result NSLog Thegcdof83and240is i gcd 83 240 pooldrain return0 Program13 5OutputThegcdof150and35is5Thegcdof1026and405is27Thegcdof83and240is1 13 2 2函数的返回结果 函数gcd规定带有两个整型参数 该函数通过形参名称u和v来指明这些参数 将变量temp声明为整型之后 该程序将在终端显示参数u v的值和相关消息 然后 这个函数计算并返回这两个整数的最大公约数 表达式result gcd 150 35 使用参数150和35来调用函数gcd 并且将返回值存储到变量result 若省略函数的返回类型声明 如果该函数确实返回任何值 编译器就会假设该值为整数 13 2 2函数的返回结果 Ojective C语言编译器假设函数的默认返回值是整型值 无论什么时候调用一个函数 编译器都会假设这个函数的返回类型为int 除非发生以下两种情况之一 在遇到函数调用之前 已经在程序中定义了该函数 在遇到函数调用之前 已经声明了函数的返回值类型 声明函数的返回值类型和参数类型称为原型 prototype 声明 函数声明不仅用于声明函数的返回类型 而且用于告知编译器 该函数带有多少参数及其类型 这类似于定义新类时在 interface部分中声明方法 13 2 2函数的返回结果 要将absoluteValue定义为一个返回float型值并带有一个float类型参数的函数 可以使用以下原型声明 floatabsoluteValue float 可以看到 只需要在圆括号中指定参数类型 而不是参数名称 如果愿意 可以选择在类型之后指定 伪 名称 floatabsoluteValue floatx 这个名称和函数定义所用到的不必相同 编译器会忽略它 编写原型声明最简单的方法是简单地复制函数实际定义的第一行代码 记住在结尾处添加分号 13 2 2函数的返回结果 如果函数的参数数目不定 比如NSLog和scanf 必须告知编译器 如下声明 voidNSLog NSString format 告知编译器 NSLog将使用一个NSString对象作为它的第一个参数 之后是任意数目的附加参数 的用途 NSLog和scanf在一个特殊文件Foundation Foundation h中声明 这就是为什么要在每个程序的开头添加下面一行语句 import如果没有这一行语句 编译器可以假设NSLog使用固定数目的参数 这可以导致产生不正确的代码 13 2 2函数的返回结果 只有已经在调用函数之前添加了函数的定义或声明了该函数及其参数类型时 编译器才会在调用该函数时自动将参数转换成相应的类型 下面是关于函数的一些注意事项和建议 默认情况下 编译器假设函数返回int定义返回值为int的函数时 直接将它定义为int当定义没有返回值的函数时 将它定义为void只有当前面已经定义或声明了这个函数 编译器才会将参数转换成函数认可的类型 13 2 2函数的返回结果 在程序中声明所有函数 即使它们在被调用之前巳经定义了 将来你可能决定将这些函数移到文件的其他位置或者移到另一个文件中 好的策略是将函数声明放到一个头文件中 然后只将这个头文件导入 import 你的模块即可 函数的默认作用域是任何与该函数链接在一起的文件中的任何函数或方法都可以调用它 通过将其定义为static 静态 可以限制函数的作用域 将关键字static放在函数声明前即可 如下所示 Staticintgcd intu intv 静态函数只可以由和该函数定义位于同一文件的其他函数或者方法调用 13 2 3函数 方法和数组 要向函数或方法传递单个数组元素 使用常规方式将数组元素指定为参数 因此 如果有一个用来计算平方根的函数squareRoot 并且想要计算averages i 的平方根并将结果赋给名为sq root result的变量 使用如下表达式即可 sq root result squareRoot averages i 向函数或方法传递整个数组是完全不同的情况 要传递数组 只需在函数调用或者方法调用中列出数组名称 并且不需要任何下标 下面的表达式将数组grade scores中的100个元素都传递给名为minimum的函数 minimum grade scores 13 2 3函数 方法和数组 下面有一个函数 它寻找包含指定元素个数的数组中的最小整数值 Functiontofindtheminimuminanarrayintminimum intvalues intnumElements intminValue i minValue values 0 for i 1 i numElements i if values i minValue minValue values i return minValue 13 2 3函数 方法和数组 函数minimum定义为带有两个参数 第一个是要査找最小数的数组 第二个是数组中的元素个数 在函数头中 values之后的一对方括号用来告知Objective C编译器 values是整型数组 编译器并不关心这个数组有多大 如果函数或者方法更改了数组元素的值 那么这个变化将影响到传递到该函数或方法的原始数组 而且这个变化在函数或方法执行完之后依然有效 调用函数或方法时 作为参数传递的值将被复制到相应的形参中 但是 使用数组时 并非将整个数组的内容复制到形参数组中 而是传递一个指针 它表示数组所在的计算机内存地址 所以 对形参数组所作的所有更改实际上都是对原始数组而不是数组的副本执行的 因此 函数或方法返回时 这些变化仍然有效 13 2 3函数 方法和数组 多维数组元素可以像任何普通变量或一维数组元素那样传递给函数或方法 语句 result squareRoot matrix i j 调用squareRoot函数 同时传递matrix i j 中包含的值作为参数整个多维数组可以像一维数组那样当作参数传递 只要列出数组名称即可 比如 如果将矩阵measuredValues声明为整型二维数组 那么Objective C语句 scalarMultiply measuredValues constant 可以用来调用一个函数 它通过值constant求出该矩阵每个元素的乘积 在函数中任何对形参数组元素的陚值操作都会永久地更改向该函数传递的数组 13 2 3函数 方法和数组 将一个单维数组声明为形参时 规定不需指定数组的实际大小 简单地使用一对空方括号来告知编译器这个参数实际上是个数组就足够了 这并不完全适用于多维数组的情况 对于二维数组 数组的行数可以省略 但是声明必须包括数组的列数 如下声明对于100行50列的形参数组arrayValues都是合法声明 intarrayValues 100 50 intarrayValues 50 但是下面的声明不是合法声明 因为必须指明数组的列数 intarrayValues 100 intarrayValues 13 3结构 除了数组之外 Objective C语言还提供了另一种组合元素的工具 结构就是这种工具 它构成了本节讨论的基础 假设要在程序中存储日期 比如说7 18 03 在Objective C语言中 可以定义一个名为date的结构 它包含三个分别代表年 月 日的成分 这种定义的语法相当直观 如下所示 structdate intmonth intday intyear 13 3结构 date结构恰好定义了三个整型元素 分别名为month day和year date的定义指出了Objective C语言中的新类型 这是由于随后就可以如下将变量声明为structdate类型 structdatetoday 还可以如下另外定义一个名为purchaseDate的同类型变量 datepurchaseDate在同一行中包含两个定义 如下面一行所示 structdatetoday purchaseDate 13 3结构 不同于int float或char型变量 处理结构变量时需要特殊语法 通过指明变量名称 在之后加上句点 称为点运算符 来访问结构成员 举个例子 要将变量today的day值设置为21 可以编写如下语句 today day 21 变量名 句点和成员名称之间不允许出现空格 13 3结构 代码清单13 6将前面的讨论合成一个实际的程序 Program13 6 importintmain intargc char argv NSAutoreleasePool pool NSAutoreleasePoolalloc init structdate intmonth intday intyear 13 3结构 structdatetoday today month 9 today day 25 today year 2009 NSLog Today sdateis i i 2i today month today day today year 100 pooldrain return0 Program13 6OutputToday sdateis9 25 09 13 3结构 main函数的第一条语句定义了名为date的结构 它包含三个整型成员 分别是month day和year 在第二条语句中 变量today声明为structdate类型 所以 第一条语句只是简单地向Objective C编译器说明了date结构的外观 并没有在计算机中分配存储空间 第二条语句定义了一个structdate类型的变量 所以导致内存中分配了空间 以便存储结构变量today的三个整型成员 13 3结构 在赋值完成后 通过调用适当的NSLog语句来显示包含在结构中的值 Today year除以100的余数是在传递给NSLog函数之前计算的 这样可以使年份只显示09 NSLog中的 2i格式符号指明了最少显示两位字符 从而强制显示年份开头的0 谈到表达式的求值时 结构成员遵循的法则和Objective C语言中普通变量一样 这样 将整型的结构成员除以整数的除法和整数除法一样 如下所示 century today year 100 1 13 3结构 假设要编写一个简单的程序 它接收今天的日期作为输入数据 并向用户显示明天的日期 可以让用户输人今天的日期 然后通过一系列语句计算出明天的日期 如下 tomorrow month today month tomorrow day today day 1 tomorrow year today year 对于大多数日期来讲 上面的语句都可以得出正确结果 但是不能正确处理以下两种情况 如果今天的日期是一个月的最后一天如果今天的日期是一年的最后一天 13 3结构 Program13 7 Programtodeterminetomorrow sdate importstructdate intmonth intday intyear Functiontocalculatetomorrow sdatestructdatedateUpdate structdatetoday structdatetomorrow intnumberOfDays structdated 13 3结构 if today day numberOfDays today tomorrow day today day 1 tomorrow month today month tomorrow year today year elseif today month 12 endofyear tomorrow day 1 tomorrow month 1 tomorrow year today year 1 else endofmonthtomorrow day 1 tomorrow month today month 1 tomorrow year today year return tomorrow 13 3结构 FunctiontofindthenumberofdaysinamonthintnumberOfDays structdated intanswer BOOLisLeapYear structdated intdaysPerMonth 12 31 28 31 30 31 30 31 31 30 31 30 31 if isLeapYear d YES 13 3结构 Functiontodetermineifit saleapyearBOOLisLeapYear structdated if d year 4 0 13 3结构 intmain intargc char argv NSAutoreleasePool pool NSAutoreleasePoolalloc init structdatedateUpdate structdatetoday structdatethisDay nextDay NSLog Entertoday sdate mmddyyyy scanf i i i 13 3结构 Program13 7OutputEntertoday sdate mmddyyyy 2282012Tomorrow sdateis2 29 12 Program13 7Output Rerun Entertoday sdate mmddyyyy 1022009Tomorrow sdateis10 3 09 Program13 7Output Rerun Entertoday sdate mmddyyyy 12312010Tomorrow sdateis1 1 10 13 3结构 即使没有用到该程序中的任何类 仍然导入了Foundation h这个文件 因为你想要使用BOOL类型 并定义YES和NO 它们定义在Foundation h文件中 date结构的定义最先出现并且在所有函数之外 如果在特定函数中定义结构 那么只有这个函数知道它的存在 如果将结构定义在函数之外 那么该定义是全局的 使用全局结构定义 该程序中随后定义的任何变量都可以声明为这种结构类型 多个文件共用的结构定义都集中放在一个头文件中 然后想要使用这些结构的文件导入这个头文件 13 3结构 在main例程中 如下声明 structdatedateUpdate structdatetoday 告知编译器函数dateUpdate使用date结构作为它的参数 并且返回date结构的值 和普通变量一样 函数对于结构参数的任何更改都不会影响原结构 这些变化只影响到调用该函数是所产生的结构副本 13 3结构 将日期输入并存储在date结构变量thisDay中之后 如下调用函数dateUpdate nextDay dateUpdate thisDay 这个语句调用函数dateUpdate 同时传递date结构变量thisDay的值 在dateUpdatefunction中 原型声明intnumberOfDays structdated 告诉编译器函数numberOfDays返回一个整型值 并且带有一个date结构类型的参数 以下语句指明today将作为参数传递给numberOfDays if today day numberOfDays today 13 3结构 函数numberOfDays首先确定该日期是否为闰年并且是否为二月 前一判断通过调用另一个名为isLeapYear的函数实现 isLeapYear简单地测试作为参数传递来的date结构中所包含的年份信息 如果是闰年返回YES 反之返回NO 函数调用的层次结构 main函数调用dateUpdate函数 dateUpdate又调用numberOfDays函数 numberOfDays调用函数isLeapYear 13 3 1结构的初始化 初始化结构与初始化数组类似 将元素列在一对花括号之中 元素之间以逗号相隔 要将date结构的变量初始化为2011年7月2日 可以使用下面的语句 structdatetoday 7 2 2011 和数组的初始化一样 列出的值可以少于结构中包含的元素个数 structdatetoday 7 将today month初始化为7 但是没有给today day或者today year赋初值 它们的默认初始值是未定义的 13 3 1结构的初始化 在初始化列表中 用下面的表示方式 member value可以任意顺序初始化结构中指定的成员 如下所示 structdatetoday month 7 day 2 year 2011 structdatetoday year 2011 13 3 2结构数组 结构数组的使用方法非常直观 定义 structdatebirthdays 15 说明数组birthdays中包含15个date结构类型的元素引用数组特定结构元素的方法非常简单 birthdays 1 month 2 birthdays 1 day 22 birthdays 1 year 1996 要将数组birthdays中的第二个生日陚值为1996年2月22日 将数组中第一个日期发送给函数numberOfDays 找出该日期的月份有多少天 n numberOfDays birthdays 0 13 3 3结构中的结构 Objective C语言在定义结构方面提供了极大的灵活性 比如 可以定义一个结构 它本身包含其他结构作为自己的一个或多个成员 或者可以定义包含数组的结构 在Objective C中 通过定义新结构可以实现将日期和时间结合在一起 这个结构包含两个元素 日期和时间 下面给出定义 structdate and time structdatesdate structtimestime 13 3 3结构中的结构 该结构的第一个成员是structdate类型的 名为sdate 第二个成员是structtime类型的 名为stime 现在 可以将变量定义为date and time结构了 如下所示 structdate and timeevent 要引用变量event中的date结构 语法是一样的 event sdate要引用这些结构中的一个成员 需要在成员名称之后添加句点 event sdate month 10 13 3 3结构中的结构 变量event可以用如下方式初始化 structdate and timeevent 12 17 1989 3 30 0 将event中的date 成员设置为1989男12月17日 并将time成员设置成3点30分0秒 设置一个date and time结构数组 如下声明 structdate and timeevents 100 以下语句将数组第4个date and time元素可以用通常的方式引用为events 3 数组中第25个元素可以使用如下语句发送给函数dateUpdate events 24 sdate dateUpdate events 24 sdate 13 3 4关于结构的补充细节 将变量定义为特定结构类型的同时 声明这个结构是合法的 只需要将变量名称放在结构定义的终止分号之前即可 structdate intmonth intday intyear todaysDate purchaseDate 定义了date结构 同时也声明了变量todaysDate和purchaseDate为这个类型 13 3 4关于结构的补充细节 还可以按常规方式来给变量赋初值 structdate intmonth intday intyear todaysDate 9 25 2010 定义了date结构 同时也将变量todaysDate赋予如上初值 如果定义结构时 也定义了该结构类型的所有变量 那么可以省略结构名称 struct intmonth intday intyear dates 100 定义了包含100个元素的数组dates 每个元素都是包含年月日的结构 因为没有为这个结构提供名称 所以定义同类型变量唯一方式就是再次显式定义这个结构 13 3 4关于结构的补充细节 在Objective C中有两种包装信息的方式 一种方式是在整数内表示这些数据 然后使用第4章 数据类型和表达式 中提到的位运箅符来访问所需的位 另一种方式是用Objective C语言所谓的位字段 bitfield 来定义包装信息的结构 这种方法在定义结构时用到了特殊语法 它允许定义一个位字段并给该字段指定名称 要定义位字段 可以定义一个名为packedStruct的结构 比如 structpackedStruct unsignedintf1 1 unsignedintf2 1 unsignedintf3 1 unsignedinttype 4 unsignedintindex 9 结构packedStruct定义为包含5个成员 第一个成员名为f1 是unsignedint 成员名称之后的 1表示这个成员将占用1位 类似地 标志f2和f3定义为1位 成员type被定义只能用4位 而成员index被定义为9位 13 3 4关于结构的补充细节 编译器自动地将前面的位字段定义包装在一起 这种方式好的方面是定义为packedStruct类型的字段变量可以和一般结构成员那样进行访问 所以如果声明一个名为packedData的变量 structpackedStructpackedData 那么可以使用这个简单的变大时方便地将packedDate中的type字段设置为7 packedData type 7 还可以使用类似的表达式将该字段赋值为n packedData type n 不必考虑n的值对于type字段是否过大 只有n的低4位赋值给packedData type 13 3 4关于结构的补充细节 从位字段中提取数值同样也是自动执行的 所以 n packedData type 提取pckeData的type字段 自动根据需要将它移到低位 并将它赋给n 位字段可以用在正则表达式中 并且自动转换成整型数据 因此语句 i packedData index 5 1 是完全合法的 下面的表达式也一样 if packedData f2 这个语句测试标志f2是开还是关 关于位字段值得注意的一个事项是 不能保证字段在内部赋值时是从左到右还是从右到左 因此 如果位字段是从右向左赋值 那么f1将位于最低位 f2位于f1左边的位置 13 3 4关于结构的补充细节 还可以在包含位字段的结构中包含正常的数据类型 因此 如果想要定义包含一个int 一个插入和两个1位标志的结构 下面的定义是合法的 structtable entry intcount charc unsignedintf1 1 unsignedintf2 1 位字段在结构定义中被包装成单位 units 单位的大小由现实来定义 并且最可能是一个字大小 Object C编译器并不会因为尝试优化存储空间 而重新组织位字段定义 13 3 4关于结构的补充细节 可以指定没有名称的位字段来跳过字中的某些位 比如下面的语句 structx entry unsignedinttype 4 unsignedint 3 unsignedintcount 9 定义了一个x entry结构 它包含一个名为tyoe的4位字段和一个名为count的9位字段 未命名的字段表示分开type和count字段的3个位 长度为0的未命名字段可以用来强制调整结构中的下一个字段作为单位边界的开始点 13 3 5不要忘记面向对象编程思想 现在你知道如何定义结构来存储日期 并且编写了各种例程来操纵这些date结构 但是 面向对象编程又体现在哪里 难道不应该建立一个名为Date的类 然后构造方法来使用Date对象 这难道不是一种更好的方法 当然 答案是肯定的 本节讲述在程序中存储日期的讨论时 这是希望你能够思考的问题 当然 如果必须在程序中处理大量日期 那么定义一个类和方法是更好的途径 事实上 Foundation框架有两个类NSDate和NSCalendarDate用于这个目的 13 4指针 指针允许你髙效地表示复杂的数据结构 更改作为参数传递给函数和方法的值 并且更准确而髙效地处理数组 指针对于对象实现也很重要 要了解指针操作方式 首先必须明白间接寻址 indirection 的概念 比如 假设需要为我的打印机买一个彩色墨盒 在我工作的公司 所有的采购活动都由采购部门负责的 所以 可以打电话给负责采购的Jim 让他为我订购一个新墨盒 Jim将打电话给本地供应商店来订购该墨盒 这样 事实上我获得新墨盒的方式就是间接的 因为我并没有直接从供应商店处订购墨盒 这种间接方式同样是Objective C中指针的工怍方式 指针提供了间接访问特定数据项值的途径 13 4指针 假设已经定义了一个名为count的变量 如下所示 intcount 10 还可以通过以下声明定义一个名为intPtr的变量 它将允许间接访问count的值 int intPtr 星号向Objective C系统定义变量intPtr是int的指针类型 这表示intPtr在这个程序中用于间接访问一个或多个整型变量的值 在Objective C语言中 设置intPtr和count之间的间接引用 13 4指针 代码清单13 8演示两个基本的指针运算符 地址运算符 和间接寻址运算符 Program13 8 Programtoillustratepointers importintmain intargc char argv NSAutoreleasePool pool NSAutoreleasePoolalloc init intcount 10 x int intPtr intPtr Program13 8Outputcount 10 x 10 13 4指针 变量count和x以常规方式声明为整型变量 变量intPtr声明为 int指针 类型 这两个声明行可以合并为一行 如下所示 intcount 10 x intPtr 然后 对变量count应用地址运算符 创建该变量的指针 然后程序将该指针赋值给变量intPtr 程序中下一条语句k intPtr 执行过程如下 间接运算符告知Objective C系统创建变量intPtr 它包含指向另一个数据项的指针 然后这个指针用来访问所需的数据项 该数据项的类型是由指针变量的声明指定的 13 4指针 代码清单13 9演示了指针变量一些有趣的属性 这里用到了指向字符的指针 Program13 9 importintmain intargc char argv NSAutoreleasePool pool NSAutoreleasePoolalloc init charc Q char charPtr Program13 9OutputQQ 13 4指针 定义了字符变量c并且将其初始化为字符 Q 变量charPtr定义为 char指针 类型 即无论存储在该变量中的是什么值 都应该看作字符的间接引用 即指针 可以使用常规方式给这个变量赋初值 在程序中赋给charPtr的值是指向变量c的指针 它是通过在变量c前面加上地址运算符得到的 变量charPtr的声明和初始值的分配都可以等效地使用如下两个语句表示 char charPtr charPtr 13 4指针 将指针设置指向一些值之前 指针的值是没有意义的 第一个NSLog调用仅显示变量c的内容以及charPtr所引用的变量内容 因为charPtr指向变量c 所以显示的就是c的内容 除非更改charPtr的值 否则表达式 charPtr总是访问c的值 当c的值发生变化时 charPtr的值也相应地改变 在以下表达式中将左括号赋给c 从形式上说是将字符 赋给charPtr指向的变量 即c 因为在程序的开始将c的指针存入了charPtr charPtr 13 4 1指针和结构 指针还可以指向结构 在本章的前面 定义了如下date结构 structdate intmonth intday intyear 可以定义指向structdate变量的指针变量structdate datePtr 13 4 1指针和结构 然后就可以用期望的方式使用刚才定义的变量datePtrdatePtr 通过datePtr间接访问date结构的成员括号是必需的 因为结构成员运算符比间接寻址运算符 的优先级别高 因为经常用到结构指针 所以该语言中存在着一个特殊运算符 结构指针运算符 它允许将表达式 x y更清楚地表示为x y 13 4 1指针和结构 代码清单13 6通过结构指针的槪念被重新改写成这里的代码清单13 10 Program13 10 Programtoillustratestructurepointers importintmain intargc char argv NSAutoreleasePool pool NSAutoreleasePoolalloc init structdate intmonth intday intyear 13 4 1指针和结构 structdatetoday datePtr datePtr Program13 10OutputToday sdateis9 25 09 13 4 2指针 方法和函数 可以按一般方式将指针作为参数传递给方法或函数 并且可以让函数或者方法返回指针 alloc和init方法一直都返回指针 Program13 11

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论