I'm trying to find a matching object in a tree, so I'm using ObjC fast enumeration. The problem is my method finds the matching value, hits the return line, and then sets the value to nil and keeps on iterating. Here's my method:
+ (INONode *)findByUUID:(NSString*)uuid fromRootNode:(INONode*)node
{
for (INONode * childNode in [node children]) {
if ([[node uniqueID] isEqualToString:uuid]) {
break;
}
else {
[INONode findByUUID:uuid fromRootNode:childNode];
}
}
return node;
}
When I follow code execution by setting a breakpoint, the break is hit, then goes to the return line, then back up to the statement that continues the iteration. What am I missing here?
Since your method is recursive, the return is returning you to the else branch of the if in your loop and continuing the search.
The way it is currently implemented, your method will only ever return the node passed in to it. The only return statement is return node, and node is never modified.
Here is one way you could do it:
+ (INONode *)findByUUID:(NSString*)uuid fromRootNode:(INONode*)node
{
// Check the root node
if ([[node uniqueID] isEqualToString:uuid]) {
return node;
}
// Check each child
for (INONode * childNode in [node children]) {
node = [INONode findByUUID:uuid fromRootNode:childNode];
if (node) {
return node;
}
}
return nil;
}
Related
I am doing a project for nand2tetris. We write a program in Jack and test it on VMEmulator. The class looks like this:
class List {
field int data;
field List next;
/* Creates a new List object. */
constructor List new(int car, List cdr) {
let data = car;
let next = cdr;
return this;
}
/* Disposes this List by recursively disposing its tail. */
method void dispose() {
if (~(next = null)) {
do next.dispose();
}
// Use an OS routine to recycle the memory held by this object.
do Memory.deAlloc(this);
return;
}
/* Prints the list*/
method void print() {
do Output.printString(" -> ");
do Output.printInt(data);
if (~(next = null)) {
do next.print();
}
return;
}
/* Inserts the argument in the right position of the list (ascending order)*/
method void insertInOrder(int ins){
var List prev, curr, insert;
let prev = this;
let curr = prev.getnext();
while (ins > prev.getdata()){
if (ins < curr.getdata()){
let insert = List.new(ins, curr);
do prev.setnext(insert);
}
else{
let prev = prev.getnext();
let curr = prev.getnext();
}
}
return;
}
/* Searches the argument in the list, if found, it returns the corresponding List object*/
method List find(int toFind){
var List temp;
var List equal;
var boolean found;
let temp = this;
let found = false;
while (~(next = null)){
if(toFind = temp.getdata()){
let equal = temp;
let found = true;
}
let temp = temp.getnext();
}
if (found){
return equal;
}
else{
return null;
}
}
method List getnext(){
return next;
}
method void setnext(List object){
let next = object;
return;
}
method int getdata(){
return data;
}
}
It has one private variable data and a pointer next. So I wrote getter and setter method to return those values. Other methods are fine only the getdata()method is incorrect. When it runs through the VMEmulator, it shows the error Out of segment space in List.getdata.3. This shows in the VMEmulator.
0function List.getdata0
1push argument0
2pop pointer0
3push this 0
4return
the error is at the 4th line return. When I change the Jack code, the same error is still at the 4th line.
What exactly is the problem in my getter method?
When you run a VM program on the VMEmulator you must first manually set the pointers to the various segments, otherwise you may get an "Out of segment space" error.
To understand the necessary settings, look at what the corresponding .tst file does. An alternative method is to insert the proposed code inside a function, since the function call automatically makes this type of setting.
You can get this error when you try to access member data of an object which is not constructed. Could it be that the List cdr in the constructor was not properly constructed?
I want to write a search function for a Binary Search Tree. How can I write it so that I can return from the base case if(root.data == node.data){return node;} without getting compiler warnings about the method returning nothing. In this case, root is an ivar that's part of the BST class that these methods are a part of.
-(Node*)search:(Node*)node{
if(root == nil){
return node;
}
if(root.data == node.data){
return node;
}
if (node.data < root.data){
root = root.left;
[self search:root];
}
if (node.data > root.data) {
root = root.right;
[self search:root];
}
}
You get the error because you don't return anything from your search: method under certain conditions. You must return something. You also don't make any use of the return value when you recursively call search:.
You also have a problem with updating root. You don't want to do that.
You probably want something more like this:
- (Node *)search:(Node *)node {
if (root == nil) {
return node;
}
if (root.data == node.data) {
return node;
} else if (node.data < root.data) {
return [self search:node.left];
} else // node.data > root.data
return [self search:node.right];
}
}
if none of your first two if tests are true, your method doesn't return anything.
Try;
if (node.data < root.data){
root = root.left;
return [self search:root];
}
if (node.data > root.data) {
root = root.right;
return [self search:root];
}
return ? // you need a return value here
I am trying to implement a removeLast function for a linked list in objective-c. My add function property works well because I can see the node I created, but when I try to remove a node it does not work. I have tried looking up general solutions for this, but have not come up with anything. Is there something special with objective-c that I should take a look at?
-(void) removeLast{
Node *newNode = [[Node alloc]init];
Node *tail = [[Node alloc]init];
if (self.head == NULL){
NSLog(#"No items to remove");
}
else{
newNode = self.head;
tail= self.head;
while (tail != NULL) {
tail = tail.next;
if (tail != NULL){
newNode = tail;
}
}
newNode.next = NULL;
}
}
I believe you've overcomplicated the algorithm. You don't need to keep a reference to the previous link if you always look one step ahead:
- (void) removeLast {
if (self.head == NULL) {
NSLog(#"Empty list");
} else if (self.head.next == NULL) {
self.head = NULL;
} else {
Node* current = self.head;
while (current.next.next != NULL)
current = current.next;
current.next = NULL;
}
}
This iterates through until it reaches the next-to-last node when current.next.next will be null. Then it makes that the last node.
I have an array of PFObjects. I'd like to search if the "Type" contains "Sushi". The filter alters the array. How can I preform this search without altering the array?
func startCheckOptions(objects: [AnyObject]) {
let filteredArray = objects.filter() {
if let type = ($0 as PFObject)["Type"] as String {
//if "type" contains "sushi", then do something instead of alter array
return type.rangeOfString("Sushi") != nil
} else {
return false
}
}
}
You can use the contains function:
func startCheckOptions(objects: [AnyObject]) -> Bool {
return contains(objects as [PFObject]) { (object) -> Bool in
if let type = object["Type"] as? String {
return type.rangeOfString("Sushi") != nil
}
else {
return false
}
}
}
if startCheckOptions(objects) {
println("yes")
}
else {
println("no")
}
This has the advantage of not building a new array containing the matching objects and stopping on the first match.
In this case you'd be better off protecting the objects cast (or really handling one time somewhere else) by casting it to [PFObject] ASAP. Leaving AnyObject references floating around can only lead to confusion and heartache.
filter() does not alter an array, but it returns a new array. What you have above is correct. objects will be the original array, and filteredArray will be the new array consistent of objects where "type" is "sushi".
I was writing simple refactoring and noticed a strange thing. The comment line before the node I am rewriting disappears after refactoring. Also comments after the node in question are transferred inside the node and break the indentation in the new place. This is very strange and I want to ask if it is a bug in jdt or I did something wrong and oblivious.
For example my code suppose to refactor if-else statements in a way that the shortest branch would appear first.
when I try to refactor this:
// pre
if(a==6) {
a = 5;
return false;
} else {
a++;
}
//post
I get this:
if (!(a==6)) {
a++;
}
//post
else {
a = 5;
return false;
}
The relevant snippet where the refactoring is done:
protected ASTRewrite createRewrite(CompilationUnit cu, SubProgressMonitor pm) {
pm.beginTask("Creating rewrite operation...", 1);
final AST ast = cu.getAST();
final ASTRewrite rewrite = ASTRewrite.create(ast);
cu.accept(new ASTVisitor() {
public boolean visit(IfStatement node) {
if (node.getStartPosition() > selection.getOffset() + selection.getLength() || node.getStartPosition() < selection.getOffset())
return true;
if (node.getElseStatement() == null)
return true;
int thenCount = countNodes(node.getThenStatement());
int elseCount = countNodes(node.getElseStatement());
if(thenCount <= elseCount)
return true;
IfStatement newnode = ast.newIfStatement();
PrefixExpression neg = negateExpression(ast, rewrite, node.getExpression());
newnode.setExpression(neg);
newnode.setThenStatement((org.eclipse.jdt.core.dom.Statement) rewrite.createMoveTarget(node.getElseStatement()));
newnode.setElseStatement((org.eclipse.jdt.core.dom.Statement) rewrite.createMoveTarget(node.getThenStatement()));
rewrite.replace(node, newnode, null);
return true;
}
});
pm.done();
return rewrite;
}
The // pre comment goes away because the parser considers it to be part of the next statement (represented by node), which you replace with newNode. When node goes away, so does the attached comment.
still thinking about why the // post ends up where it does... Try replacing the newNode before setting its then and else statements