我正在尝试构建一个树来存储USB设备信息。我以为我会使用NSMutableArray和NSMutableDictionary来包含这些信息。我的问题是,我从未学过软件工程 - 我正在学习 - 而且我对树理论一无所知。 我将我的树基于USB位置ID,这是八个半字节长。据我了解,每个半字节代表树的一层(如果你看到我的意思)。我写了一些测试代码,看看我是否可以正确构建我的树 - 而且,遗憾的是,似乎我不能![/ p>
#import <Foundation/Foundation.h>
#define MAXCHILDREN 0xf
NSDictionary* AddItemToTree(NSDictionary* nodeEntry, unsigned int value, int depth)
{
// Convert the value into a set of nibbles
char *bytes = (char *)&value;
char byte = bytes[depth];
NSMutableDictionary* thisEntry = [[[NSMutableDictionary alloc] initWithDictionary:nodeEntry] autorelease];
if (byte == 0)
{
[thisEntry setObject:[NSString stringWithFormat:@"%08x",value] forKey:@"Value"];
[thisEntry setObject:[NSString stringWithFormat:@"%08x",byte] forKey:@"Byte"];
[thisEntry setObject:[NSNumber numberWithInt:depth] forKey:@"Depth"];
return thisEntry;
}
if(![[thisEntry allKeys]containsObject:@"ChildEntries"])
{
NSMutableArray* childArray = [[NSMutableArray alloc]init];
NSMutableDictionary* newNode = [[NSMutableDictionary alloc] init];
[childArray addObject:AddItemToTree(newNode,value,++depth)];
[thisEntry setObject:[NSNumber numberWithInt:depth] forKey:@"Depth"];
[thisEntry setObject:[NSString stringWithFormat:@"%08x",value] forKey:@"Value"];
[thisEntry setObject:[NSString stringWithFormat:@"%08x",byte] forKey:@"Byte"];
[thisEntry setObject:childArray forKey:@"ChildEntries"];
[newNode release];
[childArray release];
}
else
{
[[thisEntry objectForKey:@"ChildEntries"]addObject:AddItemToTree(thisEntry,value, ++depth)];
}
return thisEntry;
}
int main(int argc, char *argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSMutableDictionary* treenode=[[NSMutableDictionary alloc]init];
char bytearray[4] = {0x0F, 0x0F, 0x02, 0x00};
unsigned int *value = (unsigned int*)bytearray;
char bytearray2[4] = {0x0F, 0x02, 0x00, 0x00};
unsigned int *value2 = (unsigned int*)bytearray2;
char bytearray3[4] = {0x0F, 0x02, 0x00, 0x00};
unsigned int *value3 = (unsigned int*)bytearray3;
[treenode setObject:[NSNumber numberWithInt:0] forKey:@"Depth"];
[treenode setObject:[NSString stringWithFormat:@"%08x",*value] forKey:@"Value"];
[treenode setObject:AddItemToTree(treenode,*value, 0) forKey:@"ChildEntries"];
// [[treenode objectForKey:@"ChildEntries"]addObject:AddItemToTree(treenode,*value2, 0)];
[treenode writeToFile:@"/Users/headbanger/Desktop/test.plist" atomically:YES];
[pool release];
}
添加一个USB位置ID可以很好地工作。添加第二个(通过取消注释main中的行)会导致SIGABRT。我确信它非常简单,而且我犯了一个典型的新手错误。但是,这对我来说并不明显,你能提供的任何帮助都会受到欢迎 我的树需要看起来像这样:
F-
|--F-
| |--2
|
|--2
即使尝试添加第三个字节数组,这个树也应该是真的。
如果你能回答问题而不是USB特定那么那将是最有帮助的,因为我真的很想理解关于树木和我做错了什么。也就是说,如果有一种快速简便的方法可以在Objective-C中为我建造一棵树,那么我很乐意听到它。
所以,请专家,有人可以告诉我我做错了什么吗?谢谢你的时间。
答案 0 :(得分:1)
一个问题是您将字典设置为ChildEntries的类型:
[treenode setObject:AddItemToTree(treenode,*value, 0) forKey:@"ChildEntries"];
但是在其他地方你试图将它用作NSMutableArray(请注意addObject:方法):
[[thisEntry objectForKey:@"ChildEntries"]addObject:AddItemToTree(thisEntry,value, ++depth)];
为了解决这个问题,你可以在主力中做到
[treenode setObject:[[NSMutableArray alloc] initWithObjects:AddItemToTree(treenode,*value, 0), nil]forKey:@"Children"];
但是即使你的递归进展到0x00字节if (byte==0)
,我认为,从心理上检查它,它会添加重复的孩子并产生一个真正深度的树。
如果您没有收到带有SIGABORT的错误方法addObject
的消息,那么您的环境有问题。
[treenode setObject:[[NSMutableArray alloc] initWithObjects:AddItemToTree(treenode,*value, 0), nil]forKey:@"Children"];
如果你写的话,更容易扫描并且不容易出错:
NSString * const kChildren = @"Children";
// ...
NSMutableArray *children = [[NSMutableArray alloc] initWithObjects:AddItemToTree(treenode,*value, 0), nil];
[treenode setObject:children forKey:kChildren];
样式不是很客观 - c-ish,你可以使用NSUInteger和NSData代替unsigned int和char数组。
您应首先编写一个通用树,然后将其用于您的目的。这是我的树例子。它很丑,但它是我的。如你所见,这是常识。您可以设置条件,例如,每个节点有两个子节点,左子节点&lt; root&lt;正确的孩子,然后你会得到一个二元搜索树,它具有更好的属性来查找东西。但是我猜这会带你更多的代码。
#import <Foundation/Foundation.h>
typedef NS_ENUM(unsigned char, MyTreeVisitingOrder) {
MyTreeOrderDepthFirst,
MyTreeOrderValueFirst
};
#define Tree NSObject<MyTree>
@protocol MyTree
@property (nonatomic,strong) NSObject<NSCopying>* key;
@property (nonatomic,strong) NSObject *value;
@property (nonatomic,strong) NSMutableDictionary *children;
-(void) insertChild:(Tree*)node;
-(void) each:(void(^)(NSObject*))block order:(MyTreeVisitingOrder)order;
@end
@interface TreeImpl : NSObject <MyTree>
-(id) init __attribute__((unavailable("disabled")));
@end
@implementation TreeImpl
@synthesize key = _key;
@synthesize value = _value;
@synthesize children = _children;
-(id) initWithKey:(NSObject<NSCopying>*)key value:(NSObject*)value {
self = [super init];
if (self){
_key = key;
_value = value;
_children = [NSMutableDictionary new];
}
return self;
}
-(void) insertChild:(Tree*)node {
[_children setObject:node forKey:node.key];
}
-(void) each:(void(^)(NSObject*))block order:(MyTreeVisitingOrder)order {
switch (order) {
case MyTreeOrderDepthFirst:{
if (_children) {
for (id key in _children){
[[_children objectForKey:key] each:block order:order];
}
}
block(_value);
break;
}
case MyTreeOrderValueFirst:{
block(_value);
if (_children) {
for (id key in _children){
[[_children objectForKey:key] each:block order:order];
}
}
break;
}
}
}
@end
int main(int argc, char *argv[]) {
@autoreleasepool {
TreeImpl *a = [[TreeImpl alloc] initWithKey:@"A" value:@"A"];
TreeImpl *b = [[TreeImpl alloc] initWithKey:@"B" value:@"B"];
TreeImpl *c = [[TreeImpl alloc] initWithKey:@"C" value:@"C"];
[a insertChild:b];
[a insertChild:c];
[a each:^(NSObject* value) {
NSLog(@"> %@",value);
} order:MyTreeOrderValueFirst];
return EXIT_SUCCESS;
}
}