Problem with array of char arrays

Hello
I'm having a bit of trouble with an array.

In my .h file I have this variable char *m_menus[5][10];

In my .cpp file i assign values to it like this

*m_menus[0] = "Engine";
*m_menus[0][6] = '\0';
*m_menus[1] = "GPS";
*m_menus[1][3] = '\0';
*m_menus[2] = "Sensors";
*m_menus[2][7] = '\0';
*m_menus[3] = "Settings";
*m_menus[3][8] = '\0';
*m_menus[4] = "Back";
*m_menus[4][4] = '\0';

Later when I try to print these values, only the four first values are ok.
when I print them via Serial using Serial.print(*m_menus[1...4]) the result is EngineGPSSensorsSettings

When I print it via an LCD it prints the four first and the last is just some random jibberish.

Does anyone know what the problem is?

Why not assign the values in the declaration?

m_menus[0] = "Engine";
*m_menus[0][6] = '\0';

Why do this?
The second assignment is redundant.

Serial.print(*m_menus[1...4]) the

Did you mean [0..4], or was that typo?

can you post your sketch?

Can you assign values in the .h file when I try I get this error.

/VMenu.h:32: error: a brace-enclosed initializer is not allowed here before ‘{’ token
/VMenu.h:32: error: ISO C++ forbids initialization of member ‘m_menus’
/VMenu.h:32: error: making ‘m_menus’ static
/VMenu.h:32: error: invalid in-class initialization of static data member of non-integral type ‘char* [5][10]’

Did you mean [0…4], or was that typo?

Yes I meant 0…4

Here is the code

.h file

#ifndef VMENU_H
#define VMENU_H

#include "WProgram.h"
#include "LCD4Bit.h"


class VMenu
{
public:
      VMenu();
      ~VMenu();

      void init(LCD4Bit *lcd);

      void showMenu();
      void menuUp();
      void menuDown();
      void menuLeft();
      void menuRight();
      inline void setMenuActive(boolean active) { m_menuActive = active; }

      inline int getSelectionCount() { return m_selectionCount; }
      inline int getCurrentSelection() {return m_currSelection; }
      inline boolean isMenuActive() { return m_menuActive; }

private:
      LCD4Bit *m_lcd;
      boolean m_menuActive;
      int m_currSelection;
      int m_selectionCount;
      char *m_menus[5][10];
};

#endif

.cpp file

#include "VMenu.h"

VMenu::VMenu()
{
      
}

VMenu::~VMenu()
{
}

void VMenu::init(LCD4Bit *lcd)
{
      m_lcd = lcd;
      
      *m_menus[0] = "Engine";
      *m_menus[1] = "GPS";
      *m_menus[2] = "Sensors";
      *m_menus[3] = "Settings";
      *m_menus[4] = "Back";
            
      m_menuActive = false;
      m_currSelection = 0;
      m_selectionCount = 5;
}

void VMenu::showMenu()
{
      // Debug info
      Serial.print(*m_menus[0]);
      Serial.print(*m_menus[1]);
      Serial.print(*m_menus[2]);
      Serial.print(*m_menus[3]);
      Serial.print(*m_menus[4]);

      m_menuActive = true;
      m_lcd->clear();
      m_lcd->cursorTo(1,0);
      if(m_currSelection == 0)
            m_lcd->printIn(">");
      m_lcd->printIn(*m_menus[0]);

      m_lcd->cursorTo(2, 0);
      if(m_currSelection == 1)
            m_lcd->printIn(">");
      m_lcd->printIn(*m_menus[1]);

      m_lcd->cursorTo(3, 0);
      if(m_currSelection == 2)
            m_lcd->printIn(">");
      m_lcd->printIn(*m_menus[2]);

      m_lcd->cursorTo(4, 0);
      if(m_currSelection == 3)
            m_lcd->printIn(">");
      m_lcd->printIn(*m_menus[3]);
  
      if(m_currSelection == 4)
      {
            m_lcd->cursorTo(4, 15);
            m_lcd->printIn(">");
      }
      m_lcd->cursorTo(4, 16);
      m_lcd->printIn(*m_menus[4]);
  
      
}

void VMenu::menuUp()
{
      if(m_menuActive == true && m_currSelection < 4)
      {
            m_currSelection--;
            if(m_currSelection < 0)
            {
                  m_currSelection = m_selectionCount - 2;
                  m_lcd->cursorTo(1,0);
                  m_lcd->printIn(*m_menus[0]);
                  m_lcd->printIn(" ");
                  m_lcd->cursorTo(4,0);
                  m_lcd->printIn(">");
                  m_lcd->printIn(*m_menus[m_selectionCount-2]);
    
            }
            else
            {
                  m_lcd->cursorTo(m_currSelection+2, 0);
                  m_lcd->printIn(*m_menus[m_currSelection+1]);
                  m_lcd->printIn(" ");
                  m_lcd->cursorTo(m_currSelection+1, 0);
                  m_lcd->printIn(">");
                  m_lcd->printIn(*m_menus[m_currSelection]);
            }
      }
}

void VMenu::menuDown()
{
      if(m_menuActive == true && m_currSelection < 4)
      {
    
            m_currSelection++;
      
                  if(m_currSelection >= m_selectionCount-1)
                  {
                        m_currSelection = 0;
                        m_lcd->cursorTo(4, 0);
                        m_lcd->printIn(*m_menus[m_selectionCount-2]);
                        m_lcd->printIn(" ");
                        m_lcd->cursorTo(1, 0);
                        m_lcd->printIn(">");
                        m_lcd->printIn(*m_menus[0]);
                  }
                  else
                  {
                        m_lcd->cursorTo( (m_currSelection + 1) - 1, 0);
                        m_lcd->printIn( *m_menus[m_currSelection - 1]);
                        m_lcd->printIn(" ");
                        m_lcd->cursorTo( (m_currSelection + 1), 0);
                        m_lcd->printIn(">");
                        m_lcd->printIn( *m_menus[m_currSelection]);
                  }  
      }
}

void VMenu::menuLeft()
{
      if(m_menuActive == true)
      {
            if(m_currSelection >= 4)
            {
                  m_lcd->cursorTo(4, 15);
                  m_lcd->printIn(" ");
                  m_lcd->printIn(*m_menus[m_selectionCount-1]);
                  m_currSelection = 3;
                  m_lcd->cursorTo(m_currSelection+1, 0);
                  m_lcd->printIn(">");
                  m_lcd->printIn(*m_menus[m_currSelection]);
            } 
      }
}

void VMenu::menuRight()
{
      if(m_menuActive == true)
      {
            if(m_currSelection < 4 )
            {
                  m_lcd->cursorTo(m_currSelection+1, 0);
                  m_lcd->printIn(*m_menus[m_currSelection]);
                  m_lcd->printIn(" ");        
                  m_currSelection = 4;
                  m_lcd->cursorTo(4, 15);
                  m_lcd->printIn(">");
                  m_lcd->printIn(*m_menus[m_currSelection]);        
            }
      }
}

On second glance,

*m_menus[0] = “Engine”;

looks completely wrong - should be "m_menus [0] =“Engine”; "

char *m_menus[5];

void setup () {
m_menus[0] = "Engine";
m_menus[1] = "GPS";
m_menus[2] = "Sensors";
m_menus[3] = "Settings";
m_menus[4] = "Back";


 for (int i = 0; i < 5; ++i) {
  Serial.println (m_menus [i]); 
 }

Works perfectly.

In header:

static char *m_menus[5][10];

In source:

char* VMenu::m_menus[5][10] = {
  "123456789",
  "123456789",
  "123456789",
  "123456789",
  "123456789"
};

Or you could pass a global initialized array of menu labels to the constructor.

[edit]Using a static array will prevent you from initializing multiple instances of the VMenu, and have them operating on different labels.

I think a global array passed as a parameter to the constructor is the best choise.[/edit]

[edit]Thank you AWOL. Strings no longer 11 bytes. :)[/edit]

AlphaBeta,

static char *m_menus[5][10]; 

...

char* VMenu::m_menus[5][10] = {
  "123456789",
  "123456789",
  "123456789",
  "123456789",
  "123456789"
};

creates a 5x10 array of 50 character pointers, initializes the first 5 to point to "123456789" and leaves the remaining 45 as NULL.

I think AWOL is on the right track with

static char *m_menus[5]; 

...

char* VMenu::m_menus[5] = {
  "Engine",
  "GPS",
  "Sensors",
  "Settings",
  "Back"
};

Obviously the * should not be in the code I posted.

Just me baing lazy, I copy-pasted OPs code.

Code without *:
In header:

static char m_menus[5][10];

In source:

char VMenu::m_menus[5][10] = {
  "123456789",
  "123456789",
  "123456789",
  "123456789",
  "123456789"
};

[edit]Of course. You kould just use mikalharts code, as that is equally correct.
Thanks for noticing mikal.[/edit]

It works now. Thanks for the help everyone.

btw I was playing around with the original code that I posted and if I inceased the array to eg. char *m_menus[8][10]; instead of char *m_menus[5][10]; it also worked. But how come?

It works now. Thanks for the help everyone

Well, yes, sort of. Problem is, you're wasting RAM (which may or may not be a problem further down the line).

Your mission, should you chose to accept it, is to investigate the use of progmem for strings.
:sunglasses: