25、假设你开发了一个矩形类,将其中一个方法标记为指定初始化器。现在有一个正方形类继承自矩形类,按照以下声明为正方形类添加一个初始化器方法:-(id) initWithSide: (int) side;
以下是为
类添加
Square
方法的实现:
initWithSide:
#import "Square.h"
@implementation Square : Rectangle
- (id)initWithSide:(int)side {
self = [super init];
if (self) {
[self setSide:side];
}
return self;
}
- (void)setSide:(int)s {
[self setWidth:s andHeight:s];
}
- (int)side {
return self.width;
}
@end
在上述代码中,
方法首先调用父类的
initWithSide:
方法进行初始化,若初始化成功,则调用
init
方法设置正方形的边长。
setSide:
26、在Fraction类的add:方法中添加一个计数器,以统计该方法被调用的次数。如何获取计数器的值?
要在Fraction类的
方法中添加计数器,可在类中定义一个静态变量作为计数器。在
add:
方法中每次调用时将该计数器加1。要获取计数器的值,可以提供一个类方法来返回该计数器的值。示例代码如下:
add:
#import <Foundation/Foundation.h>
// Define the Fraction class
@interface Fraction : NSObject
@property int numerator, denominator;
- (void) print;
- (void) setTo: (int) n over: (int) d;
- (double) convertToNum;
- (Fraction *) add: (Fraction *) f;
- (void) reduce;
+ (int) getAddInvocationCount; // 新增类方法用于获取计数器值
@end
static int addInvocationCount = 0; // 静态计数器变量
@implementation Fraction
// 实现add:方法,每次调用计数器加1
- (Fraction *) add: (Fraction *) f {
addInvocationCount++; // 原add:方法的实现代码
Fraction *result = [[Fraction alloc] init];
result.numerator = numerator * f.denominator + denominator * f.numerator;
result.denominator = denominator * f.denominator;
[result reduce];
return result;
}
// 实现获取计数器值的类方法
+ (int) getAddInvocationCount {
return addInvocationCount;
}
@end
在需要获取计数器值的地方调用
即可。
[Fraction getAddInvocationCount]
27、使用typedef和枚举数据类型,定义一个名为Day的类型,其可能的值为星期日、星期一、星期二、星期三、星期四、星期五和星期六。
可以使用如下代码来定义:
typedef enum { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday } Day;
28、使用typedef定义一个名为FractionObj的类型,以便能够编写如下语句:FractionObj f1 = [[Fraction alloc] init], f2 = [[Fraction alloc] init];
typedef Fraction *FractionObj;
29、根据以下定义:float f = 1.00; short int i = 100; long int l = 500L; double d = 15.00; 确定以下表达式的类型和值:f + i, l / d, i / l + f, l * i, f / 2, i / (d + f), l / (i * 2.0), l + i / (double) l
1. f + i:f 为 float 类型,i 为 short int 类型,根据类型转换规则,i 会转换为 float 类型,结果类型为 float,值为 101.00。
2. l / d:l 为 long int 类型,d 为 double 类型,l 会转换为 double 类型,结果类型为 double,值约为 33.33。
3. i / l + f:先算 i / l,i 为 short int 类型,l 为 long int 类型,i 先转换为 int 类型,再转换为 long int 类型,i / l 结果为 0(long int 类型),再加上 f(float 类型),0 转换为 float 类型,结果类型为 float,值为 1.00。
4. l * i:i 为 short int 类型,l 为 long int 类型,i 转换为 long int 类型,结果类型为 long int,值为 50000。
5. f / 2:2 为 int 类型,f 为 float 类型,2 转换为 float 类型,结果类型为 float,值为 0.50。
6. i / (d + f):先算 d + f,f 转换为 double 类型,d + f 结果为 double 类型,值为 16.00,i 为 short int 类型,转换为 double 类型,结果类型为 double,值约为 6.25。
7. l / (i * 2.0):i 转换为 double 类型,i * 2.0 结果为 double 类型,值为 200.00,l 转换为 double 类型,结果类型为 double,值为 2.50。
8. l + i / (double) l:先算 (double) l,l 转换为 double 类型,i 转换为 double 类型,i / (double) l 结果为 double 类型,值为 0.20,再加上 l(long int 类型,转换为 double 类型),结果类型为 double,值约为 500.20。
30、在Objective – C中,有一个
Fraction
类,现存在一个名为
MathOps
的类别对
Fraction
类进行扩展,扩展中已有
add
、
mul
、
sub
、
div
方法,要求扩展这个
MathOps
类别,使其还包含一个
invert
方法,该方法返回一个分数,该分数是调用者的倒数。
Fraction
MathOps
Fraction
add
mul
sub
div
MathOps
invert
要扩展
类别以包含
MathOps
方法,需要在接口部分添加该方法声明,并在实现部分添加方法定义。以下是扩展后的代码示例:
invert
#import "Fraction.h"
// 接口部分添加 invert 方法声明
@interface Fraction (MathOps)
- (Fraction *) add: (Fraction *) f;
- (Fraction *) mul: (Fraction *) f;
- (Fraction *) sub: (Fraction *) f;
- (Fraction *) div: (Fraction *) f;
- (Fraction *) invert; // 添加 invert 方法声明
@end
@implementation Fraction (MathOps)
- (Fraction *) add: (Fraction *) f
{
// To add two fractions:
// a/b + c/d = ((a*d) + (b*c)) / (b * d)
Fraction *result = [[Fraction alloc] init];
result.numerator = (self.numerator * f.denominator) + (self.denominator * f.numerator);
result.denominator = self.denominator * f.denominator;
[result reduce];
return result;
}
- (Fraction *) sub: (Fraction *) f
{
// To sub two fractions:
// a/b - c/d = ((a*d) - (b*c)) / (b * d)
Fraction *result = [[Fraction alloc] init];
result.numerator = (self.numerator * f.denominator) - (self.denominator * f.numerator);
result.denominator = self.denominator * f.denominator;
[result reduce];
return result;
}
- (Fraction *) mul: (Fraction *) f
{
Fraction *result = [[Fraction alloc] init];
result.numerator = self.numerator * f.numerator;
result.denominator = self.denominator * f.denominator;
[result reduce];
return result;
}
- (Fraction *) div: (Fraction *) f
{
Fraction *result = [[Fraction alloc] init];
result.numerator = self.numerator * f.denominator;
result.denominator = self.denominator * f.numerator;
[result reduce];
return result;
}
// invert 方法实现
- (Fraction *) invert
{
Fraction *result = [[Fraction alloc] init];
result.numerator = self.denominator;
result.denominator = self.numerator;
[result reduce];
return result;
}
@end
以上代码在
类别中添加了
MathOps
方法,该方法返回一个分数,其分子和分母是调用者的分子和分母的交换。最后对结果进行了约分处理。
invert
31、给Fraction类添加一个名为Comparison的类别。在这个类别中,根据以下声明添加两个方法:-(BOOL) isEqualTo: (Fraction ) f; -(int) compare: (Fraction ) f; 第一个方法在两个分数相同时返回YES,不同时返回NO。注意比较分数时,例如比较3/4和6/8应返回YES。第二个方法,若接收者小于参数表示的分数则返回 -1,若两者相等则返回0,若接收者大于参数表示的分数则返回1。
以下是实现该需求的代码示例:
#import "Fraction.h"
@interface Fraction (Comparison)
-(BOOL) isEqualTo: (Fraction *) f;
-(int) compare: (Fraction *) f;
@end
@implementation Fraction (Comparison)
-(BOOL) isEqualTo: (Fraction *) f {
Fraction *selfReduced = [[Fraction alloc] init];
selfReduced.numerator = self.numerator;
selfReduced.denominator = self.denominator;
[selfReduced reduce];
Fraction *fReduced = [[Fraction alloc] init];
fReduced.numerator = f.numerator;
fReduced.denominator = f.denominator;
[fReduced reduce];
return (selfReduced.numerator == fReduced.numerator) && (selfReduced.denominator == fReduced.denominator);
}
-(int) compare: (Fraction *) f {
double selfValue = (double)self.numerator / self.denominator;
double fValue = (double)f.numerator / f.denominator;
if (selfValue < fValue) {
return -1;
} else if (selfValue == fValue) {
return 0;
} else {
return 1;
}
}
@end
上述代码中,首先在接口部分声明了
和
isEqualTo:
两个方法。在实现部分,
compare:
方法将两个分数先进行约分,然后比较约分后的分子和分母是否相同;
isEqualTo:
方法将两个分数转换为小数进行比较,根据比较结果返回 -1、0 或 1。
compare:
32、为一个名为Calculator的类添加一个名为Trig的类别。在该类别中添加计算正弦、余弦和正切的方法,其声明如下:-(double) sin; -(double) cos; -(double) tan;
可以按照以下步骤为
类添加
Calculator
类别并实现相应方法:
Trig
首先,在代码中创建
类的
Calculator
类别。 由于
Trig
、
sin()
和
cos()
函数是标准C库函数,在导入
tan()
时会自动导入
Foundation.h
头文件,可直接使用这些函数来实现类别中的方法。
math.h
以下是示例代码:
#import <Foundation/Foundation.h>
@interface Calculator: NSObject
// accumulator methods
- (void) setAccumulator: (double) value;
- (void) clear;
- (double) accumulator;
// arithmetic methods
- (void) add: (double) value;
- (void) subtract: (double) value;
- (void) multiply: (double) value;
- (void) divide: (double) value;
@end
@interface Calculator (Trig)
- (double) sin;
- (double) cos;
- (double) tan;
@end
@implementation Calculator (Trig)
- (double) sin {
return sin(self.accumulator);
}
- (double) cos {
return cos(self.accumulator);
}
- (double) tan {
return tan(self.accumulator);
}
@end
上述代码中,在
类的
Calculator
类别里实现了
Trig
、
sin
和
cos
方法,它们分别调用标准C库函数计算累加器值的正弦、余弦和正切。
tan
33、给定以下接口部分:
@interface Square: NSObject -(Square *) initWithSide: (int) s; -(void) setSide: (int) s; -(int) side; -(int) area; -(int) perimeter; @end #import "Rectangle.h" @implementation Square { Rectangle *rect; } // 在此插入 Square 方法... @end
完成 Square 类的实现部分以及一个测试程序来检查其方法。注意:记得重写
init
方法,因为
initWithSide:
将是指定的初始化方法。
@interface Square: NSObject -(Square *) initWithSide: (int) s; -(void) setSide: (int) s; -(int) side; -(int) area; -(int) perimeter; @end #import "Rectangle.h" @implementation Square { Rectangle *rect; } // 在此插入 Square 方法... @end
init
initWithSide:
以下是 Square 类的完整实现以及测试程序:
#import <Foundation/Foundation.h>
#import "Rectangle.h"
@interface Square: NSObject
-(Square *) initWithSide: (int) s;
-(void) setSide: (int) s;
-(int) side;
-(int) area;
-(int) perimeter;
@end
@implementation Square {
Rectangle *rect;
}
-(instancetype)init {
return [self initWithSide: 0];
}
-(Square *)initWithSide: (int) s {
self = [super init];
if (self) {
rect = [[Rectangle alloc] init];
[self setSide: s];
}
return self;
}
-(void)setSide: (int) s {
[rect setWidth: s andHeight: s];
}
-(int)side {
return rect.width;
}
-(int)area {
return rect.width * rect.height;
}
-(int)perimeter {
return 2 * (rect.width + rect.height);
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
Square *square = [[Square alloc] initWithSide: 5];
NSLog(@"Side: %d", [square side]);
NSLog(@"Area: %d", [square area]);
NSLog(@"Perimeter: %d", [square perimeter]);
}
return 0;
}
上述代码中,
类使用
Square
作为组合对象。
Rectangle
是指定初始化方法,它会初始化
initWithSide:
对象并设置边长。
Rectangle
方法用于设置边长,
setSide:
方法用于获取边长,
side
方法计算面积,
area
方法计算周长。在
perimeter
函数中,创建了一个边长为 5 的
main
对象并测试其方法。
Square
34、在你的机器上找到系统头文件limits.h和float.h。检查这些文件的内容。如果这些文件包含其他头文件,也务必追踪并检查它们的内容。
要完成这个任务,不同操作系统的操作方式不同。
在Linux或macOS系统中,可使用命令行工具查找,如使用以下命令(可能需要管理员权限):
find / -name limits.h
find / -name float.h
找到文件后,可用文本编辑器(如vim、nano)打开查看内容。若文件包含其他头文件,可根据文件中的包含语句,按同样方法查找并查看。
在Windows系统中,可通过文件资源管理器搜索这两个文件,找到后用文本编辑器(如记事本、VS Code)打开查看,同样要处理包含的其他头文件。
35、定义一个名为 MAX3 的宏,用于求出三个值中的最大值。编写一个程序来测试这个宏的定义。
可以使用已有的
宏来定义
MAX
宏,定义如下:
MAX3
#define MAX3(a, b, c) MAX(MAX(a, b), c)
测试程序示例(以 C 语言为例):
#include <stdio.h>
#define MAX(a,b) ( ((a) > (b)) ? (a) : (b) )
#define MAX3(a, b, c) MAX(MAX(a, b), c)
int main() {
int x = 10, y = 20, z = 15;
int max = MAX3(x, y, z);
printf("三个数中的最大值是: %d
", max);
return 0;
}
36、编写一个名为 IS_UPPER_CASE 的宏,如果一个字符是大写字母,则该宏返回非零值。
#define IS_UPPER_CASE(x) ( ((x) >= 'A') && ((x) <= 'Z') )
37、编写一个名为 IS_ALPHABETIC 的宏,如果一个字符是字母字符,则该宏返回非零值。请定义该宏,并给出宏中可能用到的 IS_LOWER_CASE 宏和 IS_UPPER_CASE 宏的定义。
#define IS_ALPHABETIC(x) (IS_LOWER_CASE(x) || IS_UPPER_CASE(x))
其中
宏定义为:
IS_LOWER_CASE
#define IS_LOWER_CASE(x) ( ((x) >= 'a') && ((x) <= 'z') )
宏定义为:
IS_UPPER_CASE
#define IS_UPPER_CASE(x) ( ((x) >= 'A') && ((x) <= 'Z') )
38、编写一个名为 ABSOLUTE_VALUE 的宏,用于计算其参数的绝对值。确保该宏能正确计算类似 ABSOLUTE_VALUE (x + delta) 这样的表达式。
#define ABSOLUTE_VALUE(x) ((x) < 0 ? -(x) : (x))
此宏定义中,使用三元运算符判断参数`x`是否小于 0,若小于 0 则取其相反数,否则保持不变。同时使用括号确保在计算复杂表达式时能得到正确结果。
39、在分数计算器应用程序中添加一个“转换”按钮。当按下该按钮时,使用Fraction类的convertToNum方法生成分数结果的数值表示。将该结果转换为字符串并显示在计算器的显示屏上。
可按以下步骤实现:
在应用界面设计中添加一个“转换”按钮; 为“转换”按钮绑定点击事件处理方法; 在点击事件处理方法中,调用
类的
Fraction
方法得到分数结果的数值表示; 将得到的数值结果转换为字符串; 把转换后的字符串显示在计算器的显示屏上。
convertToNum
40、你可以为应用程序添加一个将显示在 iPhone 主屏幕上的图标。对于普通尺寸的图标(iPhone 3GS 及更早机型),图标大小应为 57×57 像素。对于视网膜显示屏的 iPhone(iPhone 4 及以后机型),图标图像文件应为 114×114 像素。在互联网上找到一个合适的计算器图像,并将分数计算器设置为使用此图像作为其应用程序图标。
设置分数计算器应用程序图标
搜索图标图像
– 在互联网上搜索合适的计算器图像。
准备图标文件
– 若应用需适配 iPhone 3GS 及更早机型,准备 57×57 像素 的图标。
– 若应用需适配 iPhone 4 及以后机型,准备 114×114 像素 的图标。
添加图标
– 将图标图像文件添加到相应的应用程序图标设置区域。
完成设置
– 完成分数计算器应用程序图标的设置。
41、如何为计算器按钮赋予自定义外观?
要让计算器按钮有自定义外观,可按以下步骤操作:
先把自己的图片添加到项目里(将图片拖入左窗格) 接着在检查器窗口把按钮类型设为“自定义” 再把“图像”设置成刚复制到项目中的文件
使用这种自定义图片的分数计算器能从苹果应用商店免费下载,其源代码发布在论坛 classroomM.com/objective-c 上。