我对树遍历进行了一些修补(我已经用一种更直接的方式解决了),但我在以下目标C逻辑中遇到了一个问题:
- (NSString *)someWrapperFunction
{
NSString *result = @"";
NSString *(^appendBlock)(int, NSString **) = ^NSString *(int a, NSString **adder){
if (a == 0)
{
// base case
return @"";
}
NSLog(@"%d", a);
*adder = [*adder stringByAppendingFormat:@"-%d-", a];
NSLog(@"adder: %@", *adder);
return [*adder stringByAppendingString:appendBlock(a-1, adder)];
};
appendBlock(5, &result);
return result;
}
基本上,我想创建一个代码块,将数字连接到给定的字符串(加法器)中。结果应该是:"-5--4--3--2--1-"
。
我在上面的代码中遇到了分段错误,但在我为树遍历编写的其他一些代码中,加法器字符串基本上没有得到更新。有什么迹象表明我在这里做错了什么吗?(内部块(内部递归)正在更新的变量是否可能被禁止,因为它已经被外部块占用,或者只是NSString
是不可变的数据类型?)
在任何情况下,我都想保持功能的设计不变;我将如何解决这个问题(使用c/objective)?
经过一些搜索和实验,我找到了解决这个问题的方法。
- 没有理由对块中的
adder
参数使用双指针。只需使用一个常规指针并相应地更新代码即可 - 错误来自于这样一个事实,即在块内部,
appendBlock
是NULL
,并且您最终取消了对试图调用它的NULL
指针的引用
这是一个有效的更新版本:
- (NSString *)someWrapperFunction
{
NSString *result = @"";
NSString *(^appendBlock)(int, NSString *);
__block __weak NSString *(^weakBlock)(int, NSString *);
weakBlock = appendBlock = ^NSString *(int a, NSString *adder){
NSString *(^innerBlock)(int, NSString *) = weakBlock;
if (a == 0)
{
// base case
return @"";
}
NSLog(@"%d", a);
adder = [adder stringByAppendingFormat:@"-%d-", a];
NSLog(@"adder: %@", adder);
// Split this update to make it easier to debug.
NSString *update = innerBlock(a-1, adder);
return [adder stringByAppendingString:update];
};
appendBlock(5, result);
return result;
}
输出:"-5--4--3--2--1-"
这个更新是为#1点重写的(这实际上与你的原始问题无关。
为了解决点#2,此更新创建原始appendBlock
变量以及对同一块的新__block __weak weakBlock
引用。然后在块内部,创建一个新的(强)块指针来引用弱块指针。如果不使用弱指针,代码可以工作,但会引起警告。