Search code examples
c++functionprogram-entry-point

C++ function missing after change in main


Just for clarification, currently using Repl.it. If this problem is due to Repl.it, that'll be it.

I am trying to make multiple state machines that influence each other through different states (Happy, Sad, or Mad). Each machine can talk: say what state they're in; or interact with a different machine, thus changing one of the machine's states;

The problem I have with my code is the everyone function, allowing every state machine in an array to say their states. Whenever something is changed in the main function, the everyone function just doesn't run anymore. I'm sorry that this post is really long, mostly due to any omissions causes the function to break.

This is my code:

using namespace std;

enum Mood {Happy, Sad, Mad, Default};

class StateMac {
  Mood state;      //The machine's current state

  /* Other methods no shown */

  //Returns a string relative to their current state
  string talk() {
    switch(state) {
      case Happy : return "I'm happy!";
      case Sad : return "I'm sad...";
      case Mad : return "I'm Mad!!!";
      case Default : return "...";
    }
  }

  //Compares the states between two machines
  bool compare(StateMac aStateMachine) {
    if (state == aStateMachine.getState()) {
      return true;
    }
    return false;
  }
};

//Gets size of a state machine array by comparing each to a default machine
int getSMarSize(StateMac SMar[]) {
  int counter = 0;
  for (int i = 0; i < 100; i++) {
    if (SMar[i].compare(StateMac())) { 
      break;
    } else {
      counter += 1;
    }
  }
  return counter;
}

//Receives an array of state machines and makes each of them say their states,
void everyone(StateMac SMar[]) {
  for (int i; i < getSMarSize(SMar); i++) {
    cout << "SM" << i << ": " << SMar[i].talk() << endl;
  }
}

int main() {
  //Array with 4 state machines
  StateMac ar[] = {StateMac(Happy), StateMac(Sad), StateMac(Mad), StateMac()};

  //Have everyone say their states
  everyone(ar);

  //Does same as above but line-by-line for each machine
  cout << "SM0: " << ar[0].talk() << endl;
  cout << "SM1: " << ar[1].talk() << endl;
  cout << "SM2: " << ar[2].talk() << endl;

  //Other functions
  string response = ar[0].interact(&ar[2]);
  cout << "SM0 to SM1: " << response << endl;
  cout << "SM1: " << ar[1].talk() << endl;
  response = ar[0].interact(&ar[2]);
  cout << "SM0 to SM2: " << response << endl;
  cout << "SM2: " << ar[2].talk() << endl;
  response = ar[1].interact(&ar[2]);
  cout << "SM0 to SM2: " << response << endl;
  cout << "SM0: " << ar[0].talk() << endl;
  cout << "SM1: " << ar[1].talk() << endl;
  cout << "SM2: " << ar[2].talk() << endl;
}

Producing this result:

SM0: I'm happy!   //From everyone function
SM1: I'm sad...
SM2: I'm Mad!!!
SM0: I'm happy!   //From line-by-line
SM1: I'm sad...
SM2: I'm Mad!!!
SM0 to SM1: There's nothing to be mad about!   //Other functions
SM1: I'm sad...
SM0 to SM2: That guy!!!
SM2: I'm happy!
SM0 to SM2: You look happy, might as well forget about that.
SM0: I'm Mad!!!
SM1: I'm sad...
SM2: I'm happy!

Everything looks good in the result as of now. However, if I am to add, change, or delete any line in the main function, all of a sudden, the everyone function doesn't run anymore.

For example, I changed one of the responses in the main function:

everyone(ar);
cout << "SM0: " << ar[0].talk() << endl;
cout << "SM1: " << ar[1].talk() << endl;
cout << "SM2: " << ar[2].talk() << endl;
string response = "";                       //Changed here
cout << "SM0 to SM1: " << response << endl;
cout << "SM1: " << ar[1].talk() << endl;
response = ar[0].interact(&ar[2]);
cout << "SM0 to SM2: " << response << endl;
cout << "SM2: " << ar[2].talk() << endl;
response = ar[1].interact(&ar[2]);
cout << "SM0 to SM2: " << response << endl;
cout << "SM0: " << ar[0].talk() << endl;
cout << "SM1: " << ar[1].talk() << endl;
cout << "SM2: " << ar[2].talk() << endl;

Creating this result, notice the missing everyone function call:

SM0: I'm happy!    //Line-by-line
SM1: I'm sad...
SM2: I'm Mad!!!
SM0 to SM1:        //Changed response
SM1: I'm sad...
SM0 to SM2: There's nothing to be mad about!
SM2: I'm happy!
SM0 to SM2: You look happy, might as well forget about that.
SM0: I'm happy!
SM1: I'm sad...
SM2: I'm happy!

Solution

  • The problem is in your function

    void everyone(StateMac SMar[]) {
      for (int i; i < getSMarSize(SMar); i++) {
        cout << "SM" << i << ": " << SMar[i].talk() << endl;
      }
    }
    

    This code does not initialize the variable i, and so it has undefined behavior. Changing this to int i = 0 should solve your problem.

    BTW, I am also puzzled by your use of the function int getSMarSize(StateMac SMar[]) to determine the size of the array of state machines. Your strategy seems to be to leave a "blank" state machine at the end of the array and counts the array length by iterating until it finds this blank state machine, much like the terminating character in a C string. Since you cannot automatically enforce that the array should end in StateMac(), unlike C/C++ can do with a C string, this is error-prone. There is no good reason to use this technique for an array in C++ -- you should either pass the length of the array as a parameter to the function, or better yet use the std::vector container.