2

什么是有效编码的最佳方法,因为这将被递归调用,并且创建大量对象是不好的。+*-/, sin,cos,sqrt,pi and x,y,a,b应该放在三个分开的if statements地方,不像现在所有东西都是分开的。同样为了可读性,制作包含 4 的 if 语句isEqualToString也不是很好。

    NSString *operation = topOfStack;
    if ([operation isEqualToString:@"+"]) {

    } else if ([@"*" isEqualToString:operation]) {

    } else if ([operation isEqualToString:@"-"]) {

    } else if ([operation isEqualToString:@"/"]) {


    } else if ([operation isEqualToString:@"sin"]) {

    } else if ([operation isEqualToString:@"cos"]) {

    } else if ([operation isEqualToString:@"sqrt"]) {

    } else if ([operation isEqualToString:@"pi"]) {


    } else if ([operation isEqualToString:@"x"]) {

    } else if ([operation isEqualToString:@"y"]) {

    } else if ([operation isEqualToString:@"a"]) {

    } else if ([operation isEqualToString:@"b"]) {

    }
4

5 回答 5

3

我不相信有最好的方法来做到这一点,但这是补充已经给出的答案的另一种选择。

创建一个 NSDictionary,将您的操作名称(sin、sqrt、-)映射到选择器,如下所示:

NSDictionary *operations = @{
    @"sin": [NSValue valueWithPointer:@selector(operationSin:)],
    /* other operations here */
};

然后你的 switch 语句变成了一个查找。

NSString *operation = topOfStack;
if(operations[operation]) {
    SEL op = [operations[operation] pointerValue];
    [self performSelector:op withObject:value];  /* Or some approximation thereof */
}
else {
    /* Default action for unknown operation */
}

或者,您可以在识别的操作上创建一个枚举,使用您的 NSDictionary 将操作名称映射到 NSNumber 装箱您的枚举值。

typedef NS_ENUM(NSUInteger, OperationType) {
    OperationTypeSin = 0L,
    OperationTypeSqrt,
    /* and so on */
    OperationTypeUnknown
};

/* And later...  */
NSDictionary *operations = @{
    @"sin": @(OperationTypeSin),
    /* you get the idea */
};

/* Finally ... */
NSString *operation = topOfStack;
OperationType opType = [operations[operation] unsignedIntegerValue];
switch(opType) {
    case OperationTypeSin:
        /* Much cleaner, and type-safe too */
}
于 2013-01-30T18:22:34.700 回答
2

准备工作:
首先将 NSString 操作转换为 int hashcode,将该 hashcode 存储在 #define 或常量中。

代码:

1)将NSString操作转换为int hashcode(tokenId)。
2)然后在该tokenId上执行 switch 语句。

int token = operationToToken(operation);
switch (token) {
case: OP_MINUS: break;
case: OP_SIN: break;
case: OP_COS: break;

}
于 2013-01-30T18:10:06.487 回答
1

首先,也许回退到 C 字符串,然后利用, , , , , ,sincossqrt几乎pia都以不同字符开头的事实:bxy

const char *s = [operation UTF8String];
switch (s[0]) {
case '+':
    // addition
    break;
case '-':
    // subtraction
    break;
case 's':
    // sine or sqrt
    switch (s[1]) {
    case 'q':
        // sqrt
        break;
    case 'i':
        // sine
        break;
    }
    break;
case 'c':
    // cosine
    break;
// et cetera...
default:
    // not found
}
于 2013-01-30T18:07:24.607 回答
1

如果您使用的是 Objective-C,那么您可以使用一些巧妙命名的选择器来做到这一点。

首先,创建一个对象来封装一个Operation.

然后,创建一个-initWithOperation:(NSString *)op方法。在此方法中,将任何符号操作(*+等)转换为唯一的字符串标识符(仅限字母)。

然后,您可以调用,但如果您希望方法具有参数,则必须自己NSSelectorFromString(stringOp)附加字符。:

获得选择器后,您可以使用 , 执行选择器-performSelector:+performSelector:或手动调用选择器。

如果您将每个选择器命名为与操作相同的名称,则不需要任何iforswitch语句,但您必须处理发送无效选择器的情况。

例如:

@interface Operation : NSObject

- (id)initWithOperation:(NSString *)op;
- (void)performOperationWithValue:(float)value;
+ (float)sin:(float)value;
// ... Other operations
@property (nonatomic, copy) NSString *theOperation;

@end

@implementation Operation
- (id)initWithOperation(NSString *)op {
    self = [super init];
    if (self) {
        // Convert symbols to unique strings
        theOperation = [[NSString alloc] initWithString:op];
    }
    return self;
}

- (void)performOperationWithValue:(float)value {
    NSString *withOneParam = [self.theOperation stringByAppendingString:@":"];
    SEL sel = NSSelectorFromString(withOneParam);
    [Operation performSelector:withOneParam withObject:[NSNumber numberWithFloat:value]];
}

// Class methods are the actual operation implementation...

在上面的例子中,我假设你已经传递@"sin"Operation对象。这只能在 Objective-C 中实现,因为您可以利用命名选择器。

于 2013-01-30T23:34:29.467 回答
0

您可以为每个符号分配一个编号,并可以实现一个开关盒。

于 2013-01-30T18:06:15.513 回答