Getting a null pointer exception - can't see why

edited March 2015 in Questions about Code

Hello.

I have been trying to edit the code so that all the tree member variables are passed in as parameters.

I think I'm getting there but I get a NullPointerException with the line

for (int i=0; i < m_state.length(); i++) {

I can see that the variable is m_state.length.

I can't for the life of me see what is causing the error.

I should say, I'm a real beginner!

The code is have is:

class Tree {

  // member variables
  int    m_lineLength;       // turtle line length
  int    m_x;                // initial x position
  int    m_y;                // initial y position
  float  m_branchAngle;      // turtle rotation at branch
  float  m_initOrientation;  // initial orientation
  String m_state;            // initial state
  float  m_scaleFactor;      // branch scale factor
  String m_F_rule;           // F-rule substitution
  String m_H_rule;           // H-rule substitution
  String m_f_rule;           // f-rule substitution
  int    m_numIterations;    // number of times to substitute

  // constructor
  // (d = line length, x & y = start position of drawing)
  Tree(int d, int x, int y, float m_branchAngle, float m_initOrientation, String m_state, float m_scaleFactor, String m_F_rule, String m_H_rule, String m_f_rule, int m_numIterations) {
    m_lineLength = d;
    m_x = x;
    m_y = y; 
    m_branchAngle = (25.7/180.0)*PI;
    m_initOrientation = -HALF_PI;
    m_scaleFactor = 1;
    m_state = "F";
    m_F_rule = "F[+F]F[-F]F";
    m_H_rule = "";
    m_f_rule = "";
    m_numIterations = 5;

    // Perform L rounds of substitutions on the initial state
    for (int k=0; k < m_numIterations; k++) {
      m_state = substitute(m_state);
    }
  }

  void draw() {
    pushMatrix();
    pushStyle();

    stroke(0);
    translate(m_x, m_y);        // initial position
    rotate(m_initOrientation);  // initial rotation

    // now walk along the state string, executing the
    // corresponding turtle command for each character
    for (int i=0; i < m_state.length(); i++) {
      turtle(m_state.charAt(i));
    }

    popStyle();
    popMatrix();
  }

  // Turtle command definitions for each character in our alphabet
  void turtle(char c) {
    switch(c) {
    case 'F': // drop through to next case
    case 'H':
      line(0, 0, m_lineLength, 0);
      translate(m_lineLength, 0);
      break;
    case 'f':
      translate(m_lineLength, 0);
      break;
    case 's':
      scale(m_scaleFactor);
      break;
    case '-':
      rotate(m_branchAngle);
      break;
    case '+':
      rotate(-m_branchAngle);
      break;
    case '[':
      pushMatrix();
      break;
    case ']':
      popMatrix();
      break;
    default:
      println("Bad character: " + c);
      exit();
    }
  }

  // apply substitution rules to string s and return the resulting string
  String substitute(String s) {
    String newState = new String();
    for (int j=0; j < s.length(); j++) {
      switch (s.charAt(j)) {
      case 'F':
        newState += m_F_rule;
        break;
      case 'H':
        newState += m_F_rule;
        break;
      case 'f':
        newState += m_f_rule;
        break;
      default:
        newState += s.charAt(j);
      }
    }
    return newState;
  }

}

and

Tree tree;

void setup() {
  int SZ = 512;  // screen size

  int d = 2;
  int x = SZ/2;
  int y = SZ;

  float m_branchAngle = (25.7/180.0)*PI;
  float m_initOrientation = -HALF_PI; 
  String m_state = "F";
  float m_scaleFactor = 1;
  String m_F_rule = "F[+F]F[-F]F";
  String m_H_rule = ""; 
  String m_f_rule = "";
  int m_numIterations = 5;

  size(SZ,SZ);
  background(255);
  noLoop();

  tree = new Tree(d, x, y, m_branchAngle, m_initOrientation, m_state, m_scaleFactor, m_F_rule, m_H_rule, m_f_rule, m_numIterations);  
}

void draw() {
  tree.draw();
}

I've spent days trying to understand constructors. I thought I had it, but... well,... I'm stuck again :)

Many thanks,

Answers

  • edited March 2015

    I spotted the error now.

    It's simple.

    ;-)

  • edited March 2015 Answer ✓

    Hello,

    it's indeed all about the constructor in line 18

         Tree
    

    The idea of a constructor is that you pass values in a constructor that get copied here into the class (its member vars / properties).

    To copy the parameters it's vital that params and class member variables have different names or that the member vars are referred to with this.

    So some people write for the parameters always temp as a suffix: dtemp, xtemp ... because the params are temporary. Or you write always _ behind a param: d_ etc.

    Or you use this. before the member vars.

    Your mistake

    Your mistake is simple that the param m_state has the same name as the class member var.

    When you say: m_state = "F"; in line 25 you in fact only change the param and the member var stays null. Hence the Null Pointer exception: (the length of) m_state is unknown.

    And you forgot to assign the param m_state into the class anyway.

    Solution

    So please say

    this.m_state = m_state; 
    

    instead in line 25. Thus you hammer the temporary param value into the class.

    Or rename the parameter in line 18 to m_stateTemp and say m_state = m_stateTemp; in line 25 - that'll do it.

    ;-)

  • You got 2 m_state field variables: 1 in the sketch and another in the Tree! @-)

  • edited March 2015

    @gotoloop: the 3rd m_state is not the issue since it's locally in setup()

    The issue is the parameter in the constructor (the 2nd m_state if you like).

    ;-)

  • I was just reporting what I 1st found out! :P

  • it's always fun to dive into code---

    ;-)

  • Thank you Chrisir (and others who replied).

    If I "Or rename the parameter in line 18 to m_stateTemp and say m_state = m_stateTemp; - that'll do it."

    Where do I change m_state = m_stateTemp ?

    I renamed (on line 18) m_state to m_stateTemp but where do I "say m_state = m_stateTemp; - that'll do it" Which line is that?

    Thanks again.

  • edited March 2015

    rename the parameter m_state in line 18 to m_stateTemp

    line 25: m_state = m_stateTemp;

    A parameter is a value the function or the constructor receives in the brackets ( ) .

    The line numbers refer to your first code above.

  • edited March 2015

    Thank you so much for your help.

    Having changed that, I get 'Bad character: n', but it doesn't even tell me which line the issue is on.

    The new code looks like this:

    class Tree {
    
      // member variables
      int    m_lineLength;       // turtle line length
      int    m_x;                // initial x position
      int    m_y;                // initial y position
      float  m_branchAngle;      // turtle rotation at branch
      float  m_initOrientation;  // initial orientation
      String m_state;            // initial state
      float  m_scaleFactor;      // branch scale factor
      String m_F_rule;           // F-rule substitution
      String m_H_rule;           // H-rule substitution
      String m_f_rule;           // f-rule substitution
      int    m_numIterations;    // number of times to substitute
    
      // constructor
      // (d = line length, x & y = start position of drawing)
      Tree(int d, int x, int y, float m_branchAngle, float m_initOrientation, String m_stateTemp, float m_scaleFactor, String m_F_rule, String m_H_rule, String m_f_rule, int m_numIterations) {
        m_lineLength = d;
        m_x = x;
        m_y = y; 
        m_branchAngle = (25.7/180.0)*PI;
        m_initOrientation = -HALF_PI;
        m_scaleFactor = 1;
        m_state = m_stateTemp;
        m_F_rule = "F[+F]F[-F]F";
        m_H_rule = "";
        m_f_rule = "";
        m_numIterations = 5;
    
        // Perform L rounds of substitutions on the initial state
        for (int k=0; k < m_numIterations; k++) {
          m_state = substitute(m_state);
        }
      }
    
      void draw() {
        pushMatrix();
        pushStyle();
    
        stroke(0);
        translate(m_x, m_y);        // initial position
        rotate(m_initOrientation);  // initial rotation
    
        // now walk along the state string, executing the
        // corresponding turtle command for each character
        for (int i=0; i < m_state.length(); i++) {
          turtle(m_state.charAt(i));
        }
    
        popStyle();
        popMatrix();
      }
    
      // Turtle command definitions for each character in our alphabet
      void turtle(char c) {
        switch(c) {
        case 'F': // drop through to next case
        case 'H':
          line(0, 0, m_lineLength, 0);
          translate(m_lineLength, 0);
          break;
        case 'f':
          translate(m_lineLength, 0);
          break;
        case 's':
          scale(m_scaleFactor);
          break;
        case '-':
          rotate(m_branchAngle);
          break;
        case '+':
          rotate(-m_branchAngle);
          break;
        case '[':
          pushMatrix();
          break;
        case ']':
          popMatrix();
          break;
        default:
          println("Bad character: " + c);
          exit();
        }
      }
    
      // apply substitution rules to string s and return the resulting string
      String substitute(String s) {
        String newState = new String();
        for (int j=0; j < s.length(); j++) {
          switch (s.charAt(j)) {
          case 'F':
            newState += m_F_rule;
            break;
          case 'H':
            newState += m_F_rule;
            break;
          case 'f':
            newState += m_f_rule;
            break;
          default:
            newState += s.charAt(j);
          }
        }
        return newState;
      }
    
    }
    

    `

  • please edit your post and format your code

  • How to post code

    when you post your code:

    • in the editor hit ctrl-t to auto format

    • copy it

    • paste it in the browser

    • leave 2 empty lines before it, 1 line after it

    • mark the code (without the 3 empty lines)

    • press C in the small command bar.

  • You might want to update your crosspost to include the information in this thread.

  • edited March 2015

    Hi ! I have the same problem, I've changed everything and now... nothing is showed on the screen... I still don't know what I'm doing wrong... Could you help me? Thank you in advance...

    Tree tree;
    
    void setup() {
      int SZ = 900;  // screen size
    
      int d = 2;
      int x = SZ/2;
      int y = SZ;
    
      float m_branchAngle = (25.7/180.0)*PI;
      float m_initOrientation = -HALF_PI; 
      String m_stateTemp= "F";
      float m_scaleFactor = 1;
      String m_F_rule = "F[+F]F[-F]F";
      String m_H_rule = ""; 
      String m_f_rule = "";
      int m_numIterations = 5;
    
    
      size(SZ, SZ);
      background(255);
      noLoop();
    
      tree = new Tree(d, x, y, m_branchAngle, m_initOrientation, m_stateTemp, m_scaleFactor, m_F_rule, m_H_rule, m_f_rule, m_numIterations);
    }
    
    void draw() {
      tree.draw();
    }
    ----------------------------------------
    class Tree {
    
      // member variables
      int    m_lineLength;       // turtle line length
      int    m_x;                // initial x position
      int    m_y;                // initial y position
      float  m_branchAngle;      // turtle rotation at branch
      float  m_initOrientation;  // initial orientation
      String m_stateTemp;            // initial state
      float  m_scaleFactor;      // branch scale factor
      String m_F_rule;           // F-rule substitution
      String m_H_rule;           // H-rule substitution
      String m_f_rule;           // f-rule substitution
      int    m_numIterations;    // number of times to substitute
    
      // constructor
      // (d = line length, x & y = start position of drawing)
      Tree(int d, int x, int y, float m_branchAngle, float m_initOrientation, String m_stateTemp, float m_scaleFactor, String m_F_rule, String m_H_rule, String m_f_rule, int m_numIterations) {
        m_lineLength = d;
        m_x = x;
        m_y = y; 
        m_branchAngle = (25.7/180.0)*PI;
        m_initOrientation = -HALF_PI;
        m_scaleFactor = 1;
        this.m_stateTemp = m_stateTemp;
        m_F_rule = "F[+F]F[-F]F";
        m_H_rule = "";                                                                              
        m_f_rule = "";
        m_numIterations = 5;
    
        // Perform L rounds of substitutions on the initial state
        for (int k=0; k < m_numIterations; k++) {
          m_stateTemp = substitute(m_stateTemp);
        }
      }
    
      void draw() {
        pushMatrix();
        pushStyle();
    
        stroke(0);
        translate(m_x, m_y);        // initial position
        rotate(m_initOrientation);  // initial rotation
    
          // now walk along the state string, executing the
        // corresponding turtle command for each character
        for (int i=0; i < m_stateTemp.length (); i++) {
          turtle(m_stateTemp.charAt(i));
        }
    
        popStyle();
        popMatrix();
      }
    
      // Turtle command definitions for each character in our alphabet
      void turtle(char c) {
        switch(c) {
        case 'F': // drop through to next case
        case 'H':
          line(0, 0, m_lineLength, 0);
          translate(m_lineLength, 0);
          break;
        case 'f':
          translate(m_lineLength, 0);
          break;
        case 's':
          scale(m_scaleFactor);
          break;
        case '-':
          rotate(m_branchAngle);
          break;
        case '+':
          rotate(-m_branchAngle);
          break;
        case '[':
          pushMatrix();
          break;
        case ']':
          popMatrix();
          break;
        default:
          println("Bad character: " + c);
          exit();
        }
      }
    
      // apply substitution rules to string s and return the resulting string
      String substitute(String s) {
        String newState = new String();
        for (int j=0; j < s.length (); j++) {
          switch (s.charAt(j)) {
          case 'F':
            newState += m_F_rule;
            break;
          case 'H':
            newState += m_F_rule;
            break;
          case 'f':
            newState += m_f_rule;
            break;
          default:
            newState += s.charAt(j);
          }
        }
        return newState;
      }
    

    }

  • edited March 2015

    Beware that rotate() in your vocabulary might not do what you expect. It won't rotate the turtle itself, it rotates the whole sketch from the origin (0, 0) point.
    In Processing, it is usually used with one or two translate() calls to move the origin before rotating (and to move it back).

  • I know you will think I'm dumb, but what am I suppose to do? ( Sorry, Processing is totally new for me and I have a lot of troubles with it)

  • I don't know what's wrong with it, but somewhere between the variables defined in setup() and those that the class actually uses, you got lost.

    Tree tree;
    
    void setup() {
      size(900,900);  
      background(255);
      noLoop(); 
      tree = new Tree();
    }
    
    void draw() {
      tree.draw();
    }
    
    class Tree {
      int    m_lineLength;       // turtle line length
      int    m_x;                // initial x position
      int    m_y;                // initial y position
      float  m_branchAngle;      // turtle rotation at branch
      float  m_initOrientation;  // initial orientation
      String m_stateTemp;            // initial state
      float  m_scaleFactor;      // branch scale factor
      String m_F_rule;           // F-rule substitution
      String m_H_rule;           // H-rule substitution
      String m_f_rule;           // f-rule substitution
      int    m_numIterations;    // number of times to substitute
    
      Tree() {
        m_lineLength = 2;
        m_x = width/2;
        m_y = height-20; 
        m_branchAngle = (25.7/180.0)*PI;
        m_initOrientation = -HALF_PI;
        m_scaleFactor = 1;
        m_stateTemp = "F";
        m_F_rule = "F[+F]F[-F]F";
        m_H_rule = "";                                                                              
        m_f_rule = "";
        m_numIterations = 5;
    
        // Perform L rounds of substitutions on the initial state
        for (int k=0; k < m_numIterations; k++) {
          m_stateTemp = substitute(m_stateTemp);
        }
      }
    
      void draw() {
        pushMatrix();
        pushStyle();
    
        stroke(0);
        translate(m_x, m_y);        // initial position
        rotate(m_initOrientation);  // initial rotation
    
          // now walk along the state string, executing the
        // corresponding turtle command for each character
        for (int i=0; i < m_stateTemp.length (); i++) {
          turtle(m_stateTemp.charAt(i));
        }
    
        popStyle();
        popMatrix();
      }
    
      // Turtle command definitions for each character in our alphabet
      void turtle(char c) {
        switch(c) {
        case 'F': // drop through to next case
        case 'H':
          line(0, 0, m_lineLength, 0);
          translate(m_lineLength, 0);
          break;
        case 'f':
          translate(m_lineLength, 0);
          break;
        case 's':
          scale(m_scaleFactor);
          break;
        case '-':
          rotate(m_branchAngle);
          break;
        case '+':
          rotate(-m_branchAngle);
          break;
        case '[':
          pushMatrix();
          break;
        case ']':
          popMatrix();
          break;
        default:
          println("Bad character: " + c);
          exit();
        }
      }
    
      // apply substitution rules to string s and return the resulting string
      String substitute(String s) {
        String newState = new String();
        for (int j=0; j < s.length (); j++) {
          switch (s.charAt(j)) {
          case 'F':
            newState += m_F_rule;
            break;
          case 'H':
            newState += m_F_rule;
            break;
          case 'f':
            newState += m_f_rule;
            break;
          default:
            newState += s.charAt(j);
          }
        }
        return newState;
      }
    }
    
  • edited March 2015

    Thanks all for the effort you've put in to your replies (on both forums Kevin!)

    I've made this change

    "rename the parameter m_state in line 18 to m_stateTemp

    line 25: m_state = m_stateTemp;"

    The Bad character: n has me completely stumped.

    My code now looks like this.

        Tree tree;
    
        void setup() {
        int SZ = 512; // screen size
    
        int d = 2;
        int x = SZ/2;
        int y = SZ;
    
        float m_branchAngle = (25.7/180.0)*PI;
        float m_initOrientation = -HALF_PI;
        String m_state = "F";
        float m_scaleFactor = 1;
        String m_F_rule = "F[+F]F[-F]F";
        String m_H_rule = "";
        String m_f_rule = "";
        int m_numIterations = 5;
    
        size(SZ,SZ);
        background(255);
        noLoop();
    
        tree = new Tree(d, x, y, m_branchAngle, m_initOrientation, m_state, m_scaleFactor, m_F_rule, m_H_rule, m_f_rule, m_numIterations);
        }
    
        void draw() {
        tree.draw();
        }
    

    and

        class Tree {
    
        // member variables
        int m_lineLength; // turtle line length
        int m_x; // initial x position
        int m_y; // initial y position
        float m_branchAngle; // turtle rotation at branch
        float m_initOrientation; // initial orientation
        String m_state; // initial state
        float m_scaleFactor; // branch scale factor
        String m_F_rule; // F-rule substitution
        String m_H_rule; // H-rule substitution
        String m_f_rule; // f-rule substitution
        int m_numIterations; // number of times to substitute
    
        // constructor
        // (d = line length, x & y = start position of drawing)
        Tree(int d, int x, int y, float m_branchAngle, float m_initOrientation, String m_stateTemp, float m_scaleFactor, String m_F_rule, String m_H_rule, String m_f_rule, int m_numIterations) {
        m_lineLength = d;
        m_x = x;
        m_y = y;
        m_branchAngle = (25.7/180.0)*PI;
        m_initOrientation = -HALF_PI;
        m_scaleFactor = 1;
        m_state = m_stateTemp;
        m_F_rule = "F[+F]F[-F]F";
        m_H_rule = "";
        m_f_rule = "";
        m_numIterations = 5;
    
        // Perform L rounds of substitutions on the initial state
        for (int k=0; k < m_numIterations; k++) {
        m_state = substitute(m_state);
        }
        }
    
        void draw() {
        pushMatrix();
        pushStyle();
    
        stroke(0);
        translate(m_x, m_y); // initial position
        rotate(m_initOrientation); // initial rotation
    
        // now walk along the state string, executing the
        // corresponding turtle command for each character
        for (int i=0; i < m_state.length(); i++) {
        turtle(m_state.charAt(i));
        }
    
        popStyle();
        popMatrix();
        }
    
        // Turtle command definitions for each character in our alphabet
        void turtle(char c) {
        switch(c) {
        case 'F': // drop through to next case
        case 'H':
        line(0, 0, m_lineLength, 0);
        translate(m_lineLength, 0);
        break;
        case 'f':
        translate(m_lineLength, 0);
        break;
        case 's':
        scale(m_scaleFactor);
        break;
        case '-':
        rotate(m_branchAngle);
        break;
        case '+':
        rotate(-m_branchAngle);
        break;
        case '[':
        pushMatrix();
        break;
        case ']':
        popMatrix();
        break;
        default:
        println("Bad character: " + c);
        exit();
        }
        }
    
        // apply substitution rules to string s and return the resulting string
        String substitute(String s) {
        String newState = new String();
        for (int j=0; j < s.length(); j++) {
        switch (s.charAt(j)) {
        case 'F':
        newState += m_F_rule;
        break;
        case 'H':
        newState += m_F_rule;
        break;
        case 'f':
        newState += m_f_rule;
        break;
        default:
        newState += s.charAt(j);
        }
        }
        return newState;
        }
    
        } 
    
  • Answer ✓

    Just lump your code into one code block, please. It's easier to copy and paste and run for those of us trying to help you debug this.

    If you comment out the call to exit(), you get some more telling output:

    Bad character: n
    Bad character: u
    Bad character: l
    Bad character: l
    

    Well, that's a problem, isn't it? Now you just need to hunt down the line that's changing m_state from "F" to "null". Hint: It's somewhere in substitute(). Bonus hint: Debugging software is the process of finding where you and the computer disagree on what the program is doing. Triple bonus hint: The computer is doing exactly what you told it to do; if it isn't doing what you want, then it's not wrong - you told it to do the wrong thing!

  • I will tfGuy. Is it normal practice to separate it (in one block) with a line of dashes or something?

    Well, the computer's an idiot - I'm telling it to draw a bloomin' tree! Literally, telling (or shouting, even!) :) Probably the same way you're wondering if I'm an actual idiot for still being stuck with you hints and bonus hints!

    So, thanks to you, I know it's here:

    // apply substitution rules to string s and return the resulting string
    String substitute(String s) {
    String newState = new String();
    for (int j=0; j < s.length(); j++) {
    switch (s.charAt(j)) {
    case 'F':
    newState += m_F_rule;
    break;
    case 'H':
    newState += m_F_rule;
    break;
    case 'f':
    newState += m_f_rule;
    break;
    default:
    newState += s.charAt(j);
    }
    }
    return newState;
    }
    
    } 
    

    Line 10? Does something need to be changed to m_stateTemp? I didn't write this part of the code. It was supplied as part of the question. I thought understood it, but obviously not as thoroughly as I thought I did.

    I really appreciate all the time you've taken here. Thank you.

  • I've got it!

    Thank you for your help all.

    My constructor code now looks like this

     // constructor
      // (d = line length, x & y = start position of drawing)
      Tree(int d, int x, int y, float Angle, float InOr, String m_s, float sF, String m_F, String m_H, String m_f, int numIt) {
        m_lineLength = d;
        m_x = x;
        m_y = y;
        m_branchAngle = Angle;
        m_initOrientation = InOr;
        m_scaleFactor = sF;
        m_state = m_s;
        m_F_rule = m_F;
        m_H_rule = m_H;
        m_f_rule = m_F;
        m_numIterations = numIt;
    

    and the values can easily be changed here

    float Angle = (25.7/180.0)*PI;
    float InOr = -HALF_PI;
    String m_s = "F";
    float sF = 1;
    String m_F = "F[+F]F[-F]F";
    String m_H = "";
    String m_f = "";
    int numIt = 5;
    

    I'd been making problems for myself with ridiculous code. All part of the learning process, I guess.

Sign In or Register to comment.