2.2 解释第一个程序
现在,你熟悉了编译并运行Objective-C程序的各个步骤,我们更详细地讲述这个程序。下面再次给出该程序。
//First program example
import<Foundation/Foundation.h>
int main(int argc, const char*argv[])
{
NSAutoreleasePool*pool=[[NSAutoreleasePool alloc]init];
NSLog(@“Programming is fun!”);
[pool drain];
return 0;
}
在Objective-C中,小写字母和大写字母是不同的。同样,Objective-C并不关心你在程序行的何处开始输入,程序行的任何位置都能输入语句。利用这个事实可以开发容易阅读的程序。
程序的第一行
//First program example
引入了注释的概念。
程序中使用的注释语句用于说明程序并增强程序的可读性。注释负责告诉该程序的读者,不管他是程序员还是其他负责维护该程序的人,这只是程序员在编写特定程序和特定语句序列时的想法。
向Objective-C程序中插入注释时,有两种方式。其一,使用两个连续的斜杠(//)。双斜杠后直到这行结尾的任何字符都将被编译器忽略。
注释还能以两个字符/和开始。它们表示注释的开始,但必须终止这种注释。要终止注释,需要再次使用字符和/,而且中间不能插入任何空格。开始/和结束/之间的所有字符都被看作注释语句的一部分,从而被Objective-C编译器忽略。注释跨越很多程序行时,通常使用这种注释格式,例如以下所示:
/*
This file implements a class called Fraction, which
represents fractional numbers.Methods allow manipulation of
fractions, such as addition, subtraction, etc.
For more information, consult the document:
/usr/docs/classes/fractions.pdf
*/
使用哪种风格的注释完全由你决定。只要注意:/*风格的注释不能嵌套使用。
在编写程序或者将其键入到计算机上时,应该养成在程序中插入注释的习惯。这种习惯有三方面的好处:首先,当特殊的程序逻辑在你的大脑中出现时就说明程序,要比程序完成后再回来重新思考这个逻辑简单得多。其次,通过在工作的早期阶段把注释插入程序中,可在调试阶段隔离和调试程序逻辑错误时受益匪浅。注释不仅可以帮助你(或者其他人)通读程序,而且还有助于指出逻辑错误的根源。最后,我甚至还发现有一个程序员实际上喜欢为程序添加注释。事实上,在调试完程序后,你很可能不喜欢再返回程序来插入注释。在开发程序过程中插入注释会使这项乏味的工作变得稍微容易。
代码清单2-1的下一个程序行
import<Foundation/Foundation.h>
告诉编译器找到并处理名为Foundation.h的文件,这是一个系统文件,就是说,这个文件不是你创建的。#import表示将该文件的信息导入或包含到程序中,在这一点上,特别像把此文件的内容键入到程序中。要导入文件Foundation.h,因为它包含程序结尾处用到的其他类和函数的有关信息。
在代码清单2-1中,程序行
int main(int argc, const char*argv[])
指定程序的名称为main,它是一个特殊名称,用于准确地表示程序将在何处开始执行。main之前的保留字int指定main返回的值类型,该值为整型(很快将更加详细地讨论这个话题)。我们将暂时忽略出现在开始和结束圆括号之间的内容。它们与名为命令行参数的内容有关,我们将在第13章中再作讨论。
认识了针对系统的main,可以准确指定这个例程要执行哪些工作。把例程的所有程序语句放入到一对花括号中,可完成这项工作。在最简单的情况下,一条语句就是一个以分号结束的表达式。系统将把位于花括号中间的所有程序语句看作main例程的组成部分。代码清单2-1有4条语句。
代码清单2-1中的第一条语句是
NSAutoreleasePool*pool=[[NSAutoreleasePool alloc]init];
这条语句为自动释放池在内存中保留了空间。我们会在第17章中全面讨论这个内容。作为模板的一部分,Xcode会将这行内容自动放入程序中,所以现在先不要管它。
下一条语句指定要调用名为NSLog的例程。传递或传送给NSLog例程的参数,或实参,是以下字符串:
@“programming is fun!”
此处@符号在位于一对双引号的字符串前面。这称为常量NSString对象。
注意如果你有一定的C程序设计经验,可能会被前面的@字符所迷惑。如果没有前面的@字符,就是在编写常量C类型的字符串;有了这个符号,就是在编写NSString字符串对象。
NSLog例程是Objective-C库中的一个函数,它仅仅显示或记录其参数(或者参数列表,很快将会看到)。但是之前它会显示该例程的执行日期和时间、程序名,以及其他我们在此不会介绍的数值。在本书的后面部分中,我们不会列出NSLog在输出前面插入的这些文本。
Objective-C的所有程序语句必须使用分号(;)结束。这就是为什么分号会在NSLog调用的结束圆括号之后立即出现。
退出程序之前,应该使用类似于下面的语句释放已分配的内存池(以及与程序相关联的对象):
[pool drain];
同样,Xcode会在程序中自动插入此行内容。我们在后面会详细介绍该语句的作用。main中的最后一条程序语句是:
return 0;
它表示要终止main的执行并送回(或返回)一个状态值0。按照约定,0意味着程序正常结束。任何非零值通常表示出现了一些问题,例如,很可能无法找到程序所需的文件。
如果你正在使用Xcode,回顾Debug Console窗口(参见图2-8),会发现在NSLog输出的行之后将显示如下:
The Debugger has exited with status 0.
你应该理解这条消息在此处的含义。
现在,我们将结束第一个程序的讨论,对它进行修改以便同时显示短语“And programming in Objective-C is even more fun!”。这项工作可以通过简单地添加另一个对NSLog例程的调用来实现,如代码清单2-2所示。记住,每个Objective-C程序语句必须使用分号结束。
代码清单2-2
import<Foundation/Foundation.h>
int main(int argc, const char*argv[])
{
NSAutoreleasePool*pool=[[NSAutoreleasePool alloc]init];
NSLog(@“Programming is fun!”);
NSLog(@“Programming in Objective-C is even more fun!”);
[pool drain];
return 0;
}
如果键入代码清单2-2,然后编译并运行它,你可能期望在终端上看到以下输出(同样,没有显示NSLog通常在输出前面加入的那些文本)。
代码清单2-2输出
Programming is fun!
Programming in Objective-C is even more fun!
在下一个程序例子中将看到,无需为每行输出单独调用NSLog例程。
首先,让我们看看特殊的两字符序列。反斜杠(\)和字母n,合起来称为换行符。换行符通知系统要准确完成其名称所暗示的工作:转到一个新行。任何要在换行符之后输出的字符随后将出现在显示器的下一行。事实上,换行符非常类似于一台打字机上结束符(carriage return)的概念。
研究代码清单2-3中列出的程序,并在检验输出之前尝试预测结果(不要作弊,开始!)。
代码清单2-3
import<Foundation/Foundation.h>
int main(int argc, const char*argv[])
{
NSAutoreleasePool*pool=[[NSAutoreleasePool alloc]init];
NSLog(@“Testing……\n..1\n……2\n……3”);
[pool drain];
return 0;
}
代码清单2-3输出
Testing……
..1
……2
……3