0

I'm breaking my head trying to sort out this problem, and I have not been able to sort it out. Given I have a struct:

struct person
{
     String name,
     String city,
     int age
}

I am reading a list of people from a certain file provided externally, and populating an array of this struct. This is done via a function, lets say

person * readFromFile(filename);

This function has the logic to read the file, create a variable size array of structs (adapted to the number of persons in the file), and return said array.

However, when I try to assign that outcome to a pointer, I'm not getting the elements of the array:

...
person * myPeople;
myPeople = readFromFile("/people.txt");
int n= ;// different things I-ve tried here
Serial.println("n is" + n);
for(int i=0; i<n; i++)
{ 
     Serial.println(myPeople.name + " (" + String(myPeople.age) + "), "+myPeople.city
}

I've tried several things to get the number of elements once the array is populated after researching how to do it, to know:

int n = sizeof(myPeople)/sizeof(myPeople[0]);
int n = sizeof myPeople / sizeof *myPeople;
int n = sizeof(myPeople) / sizeof(person);
int n = (&myPeople)[1] - myPeople;

But to no avail: I have 5 elements in the file, but n does never show the expected value (and of course the for loop breaks).

Can I get some assistance? what am I be doing wrong?

Thanks

ggonmar
  • 760
  • 1
  • 7
  • 28
  • 3
    You need to store the length of the array explicitly, there is no way to retrieve it from a pointer – UnholySheep Oct 23 '20 at 12:07
  • 1
    Does this answer your question? [How to find the 'sizeof' (a pointer pointing to an array)?](https://stackoverflow.com/questions/492384/how-to-find-the-sizeof-a-pointer-pointing-to-an-array) – UnholySheep Oct 23 '20 at 12:07
  • 1
    Wrap it into a struct with more info: `struct personArray { struct person *data; int totalelements; int nelements; };`... every time you `realloc()` data (when `nelements == totalelements` and you need more space) adjust `totalelements`, everytime you add a person adjust `nelements`. – pmg Oct 23 '20 at 12:14
  • 1
    Or... `person * readFromFile(filename, &nReadPersons)` , where the latter is an out-argument, populated by your function and specifies the number of items in the returned sequence. All that's left it to actually write it now. Personally I prefer doing what @pmg suggests. it keeps codependent data together, nice and tidy. – WhozCraig Oct 23 '20 at 12:18
  • uhm, thats an elegant alternative, let me try that! thank you! – ggonmar Oct 23 '20 at 13:02
  • 3
    Where do you actually allocate memory? And why on earth are you doing file handling on an Arduino? – Lundin Oct 23 '20 at 13:34
  • Also, is this about C language or Arduino C++ language? – Lundin Oct 23 '20 at 13:35
  • Another option is to use a sentinel value as the last element (similar to the 0 terminator in strings) - some out-of-band value that can't happen in normal input (like a negative age, or blank name, or similar). Then you loop until you see that sentinel. – John Bode Oct 23 '20 at 14:01
  • @Lundin Arduino C++, I'm updating the tags for this. Apologies – ggonmar Oct 23 '20 at 14:19
  • @Lundin I'm allocating the memory on the function readFromFile(). This is actually reading a JSON, using deserializeJSON, which actually gives me the number of elements with doc.size(). Then, I'm doing struct person list[doc.size()], and populating it on a for loop. Lastly, returning list as the array that contains all the people there. Probably intrincate and ineficcient, but I'm learning...! – ggonmar Oct 23 '20 at 14:24
  • Again, why on earth are you doing that on an Arduino? It's not a PC. – Lundin Oct 26 '20 at 06:21
  • I'm starting to be curious where is this question coming from: Why? because I want to experiment, becuse the project I'm trying to pull out requires so, because it's an exercise to see the capabilities of my microcontroller... in short, because why not :P – ggonmar Oct 26 '20 at 11:09

1 Answers1

1

Instead of using "String" (Whatever that is in your case.), use a fixed array of char for each string.

Like so:

struct person
{
     char name[32], /* string name has a length of 31 + 1 for NULL-termination */
     char city[32], /* string city has a length of 31 + 1 for NULL-termination */
     int age
}
paladin
  • 765
  • 6
  • 13
  • Despite my reluctancy to use char instead of String, I ended up using this as the pure only way of getting rid of my problems.... thanks! – ggonmar Dec 03 '20 at 14:04
  • No problem. You should also add the following modifier to your struct: `__attribute__((__packed__))`, it ensures that your struct will be always of the same byte-size, even on different CPU architectures. By the way, when working with pointers over structs, it's always a good idea to use the most basic data-types (if possible) within that struct. Or at least use other packed structs as data-types within that struct, which characteristics **you exactly know**. – paladin Dec 04 '20 at 14:39