在Objective C中构建USB树

时间:2013-01-29 18:07:32

标签: objective-c tree usb

我正在尝试构建一个树来存储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中为我建造一棵树,那么我很乐意听到它。
所以,请专家,有人可以告诉我我做错了什么吗?谢谢你的时间。

1 个答案:

答案 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;
    }
}