How to access an element in a List of Lists ?

Hello community,

I’m using a this list library : GitHub - luisllamasbinaburo/Arduino-List: Librería de Arduino que implementa un array dinámico
As you can see in my code below, there’s an issue when Adding both lists to the list of lists. The first and second elements are replaced by 0.

Here’s my code :

/***************************************************
Copyright (c) 2017 Luis Llamas
(www.luisllamas.es)

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License
 ****************************************************/ 
#include "ListLib.h"
 
class Child {
 public: 
 int counter; // Variable to count learned letters
 List<byte> subList1;
 List<byte> subList2;
 List<List<byte>> biggerList;

 Child(){ // constructor
   counter = 0;
 }

 void print_sublist_1(){ // Display Sublist 1
   for (byte i = 0; i < subList1.Count(); i++)
    {
    Serial.print(subList1[i]);
    Serial.print("|");
    }
 }

  void print_sublist_2(){ // Display Sublist 2
   for (byte i = 0; i < subList2.Count(); i++)
    {
    Serial.print(subList2[i]);
    Serial.print("|");
    }
 }
}; 

Child child_A = Child();

void setup(){
 Serial.begin(9600);
 
 for (byte i = 1; i <= 10; i++) // Add 10 elements 1 -> 10 to subList1
  {
    child_A.subList1.Add(i);
  }

  Serial.println("\n SUBLIST 1 :");
  child_A.print_sublist_1();
  Serial.println("");
 
 for (byte i = 11; i <= 20; i++) // Add 10 elements 11 -> 20 to subList2
  {
    child_A.subList2.Add(i);
  }

  Serial.println("\n SUBLIST 2 :");
  child_A.print_sublist_2();
  Serial.println("");

  child_A.biggerList.Add(child_A.subList1);
  child_A.biggerList.Add(child_A.subList2);

  Serial.println("\n BIGGER LIST :");
  
  for (byte i = 0; i < child_A.biggerList.Count() ; i++)
  {
    for (byte j = 0; j < child_A.biggerList[i].Count() ; j++)
    {
      Serial.print(child_A.biggerList[i][j]);
      Serial.print("|");
    }
  }
  Serial.println("");

  
}

void loop(){

}

Here’s the Serial monitor output :

What am I doing wrong ?

I think you need to use either pointers or references for the bigger list, try this declaration:

List<List<byte>&> biggerList;

is accessing a "List" element as a 2 dimensional array a valid operation on a "List"

child_A.biggerList[i][j]

Hello again,

After many tryouts, I found that my problem was with declaring an initial capacity for the list.

Now I have another technical issue :

/***************************************************
Copyright (c) 2017 Luis Llamas
(www.luisllamas.es)

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License
 ****************************************************/ 

#include "ListLib.h"

 List< List<uint8_t> > bigList(100); // List of lists with a capacity of 100
 List<uint8_t> subList11(50); // Sublist 1 with a capacity of 50
 List<uint8_t> subList12(50); // Sublist 2 with a capacity of 50

class Child {
 public: 
 int counter;
 List<uint8_t> subList1(50);
 List<uint8_t> subList2(50);
 List< List<uint8_t> > biggerList(100);

 Child(){ // constructor
   counter = 0;
   biggerList.Add(subList1);
   biggerList.Add(subList2);
 }

 void print_list()
 {
  for (int i = 0 ; i < biggerList.Count() ; i++)
    {
      for (int j = 0 ; j < biggerList[i].Count() ; j++)
      {
        Serial.print(biggerList[i][j]);
        Serial.print("|");
        delay(1);
      }
    }
 }

}; 

Child child_A = Child();

void setup() {
  // put your setup code here, to run once:

Serial.begin(9600);

bigList.Add(subList11);
bigList.Add(subList12);

for (int i = 0 ; bigList[0].IsFull()!=1; i++)
{
  bigList[0].Add(i);
}
for (int i = 0 ; bigList[1].IsFull()!=1; i++)
{
  bigList[1].Add(50+i);
}

Serial.print("bigList.Capacity: ");
Serial.println(bigList.Capacity());
Serial.print("bigList[0].Capacity: ");
Serial.println(bigList[0].Capacity()); 
Serial.print("bigList[1].Capacity: ");
Serial.println(bigList[1].Capacity());  

for (int j = 0 ; j < bigList[0].Count() ; j++)
      {
        Serial.print(bigList[0][j]);
        Serial.print("|");
        delay(1);
      }
   
Serial.println("");
for (int j = 0 ; j < bigList[1].Count() ; j++)
      {
        Serial.print(bigList[1][j]);
        Serial.print("|");
        delay(1);
      }
   Serial.println("");

}

void loop() {
  // put your main code here, to run repeatedly:

}

You will see in the code that I now can declare a List with the capacity between brackets :

List< List<uint8_t> > bigList(100); // List of lists with a capacity of 100
 List<uint8_t> subList11(50); // Sublist 1 with a capacity of 50
 List<uint8_t> subList12(50); // Sublist 2 with a capacity of 50

The problem is when I try to write the same declaration inside my Class :

class Child {
 public: 
 int counter;
 List<uint8_t> subList1(50);
 List<uint8_t> subList2(50);
 List< List<uint8_t> > biggerList(100);

The code doesn’t compile and the error i get is :

test_list_llamas_VCG_2:19: error: expected identifier before numeric constant
test_list_llamas_VCG_2:19: error: expected ',' or '...' before numeric constant
test_list_llamas_VCG_2:20: error: expected identifier before numeric constant
test_list_llamas_VCG_2:20: error: expected ',' or '...' before numeric constant
test_list_llamas_VCG_2:21: error: expected identifier before numeric constant
test_list_llamas_VCG_2:21: error: expected ',' or '...' before numeric constant
test_list_llamas_VCG_2.ino: In constructor 'Child::Child()':
test_list_llamas_VCG_2:25: error: '((Child*)this)->Child::biggerList' does not have class type
test_list_llamas_VCG_2:26: error: '((Child*)this)->Child::biggerList' does not have class type
test_list_llamas_VCG_2.ino: In member function 'void Child::print_list()':
test_list_llamas_VCG_2:31: error: '((Child*)this)->Child::biggerList' does not have class type
test_list_llamas_VCG_2:33: error: invalid types '<unresolved overloaded function type>[int]' for array subscript
test_list_llamas_VCG_2:35: error: invalid types '<unresolved overloaded function type>[int]' for array subscript
expected identifier before numeric constant

I know it must be something to do with “overloading” which I don’t understand well.
If anyone could point me out in the right direction it would be a great help.
Thanks !

You are trying to construct class variables before the class is constructed.

class Child {
 public:
 int counter;
 List<uint8_t> subList1; //Remove "(50)"
 List<uint8_t> subList2; //Remove "(50)"
 List< List<uint8_t> > biggerList; //Remove "(100)"
 Child() : subList1(50), subList2(50), biggerList(100) //Add construction of variables to class constructor
 { ... }

And btw; Why do you want to have a capacity of 100 for “biggerList” when it only contains 2 items?

EDIT: The “List” class uses a dynamic memory methodology which is known to cause problems on AVR’s (just like the “String” class) so I would be careful when using it.

Your library does not support making List of user-defined types. It only works with primitive types.

Danois90:
You are trying to construct class variables before the class is constructed.

Thank you !

Danois90:
And btw; Why do you want to have a capacity of 100 for “biggerList” when it only contains 2 items?

Right ! I got confused there ! Should just leave it a capacity of 4.

Danois90:
EDIT: The “List” class uses a dynamic memory methodology which is known to cause problems on AVR’s (just like the “String” class) so I would be careful when using it.

Do you recommend I use C language’s malloc() and free() instead ?
Isn’t there a robust way of making sure there is no memory leakage ?

Thank you !

Do you recommend I use C language's malloc() and free() instead ?

if you have a large memory resource such as on a PC. otherwise (e.g. arduino) i think it's better to preallocate and limit how many elements can be used to guarantee memory dynamically allocated in sub-function calls.

and there may be little need to use free(). you can use malloc() to allocate new elements in bunches, 10 at a time and just leave them allocated for future use when no longer needed. eventually you no longer need to malloc any more

Isn't there a robust way of making sure there is no memory leakage ?

i think Scott Meyers spent most of a book discussing the pitfals of using new and delete to prevent memory leeks