How to create an array/list that contains strings, and I can append to?

Hi! New to this, only can code a few things in Unity which is C#

I parse a JSON where I get names from images from. I want to store all the names in an array of strings and append them in a for loop when I go over the JSON.

The goal is that I save all the image names in an array. This is dynamic since I can add images when I want. After I have all the image names as a list or array, I want to pick a random image (and display it on a screen).

This is how I'd do it in C# but now I need it for Arduino :slight_smile:

 List<string> names = new List<string>();
 //If you wanted to append to the top of the list
 names.add("Tom");
 names.add("Tom2");

You could create an array with malloc and resize it using realloc, or you could use a library that implements a vector or a list. e.g.,

Better to use "new" - "malloc" is sooo 1970s.

True, but I prefer to use either malloc/realloc/free or new/delete.

Vector library does exactly what I need! Just got it working, thank you!

If you can (i.e. on any type of Arduino except 8-bit AVRs), use the standard library container std::vector: std::vector - cppreference.com

#include <vector>
#include <string>

std::vector<std::string> names;
names.reserve(2); // If you have an estimate of the size
// beforehand, this will help reduce memory fragmentation
names.push_back("Tom");
names.push_back("Tom2");

Then you could do:

#include <random>
#include <algorithm>

std::random_device rand_dev;
std::mt19937 rand_gen(rand_dev());
// Randomly shuffle the names
std::shuffle(names.begin(), names.end(), rand_gen);
// Loop over the shuffled names and display them
for (const auto &name : names) {
  show_image(name);
  delay(10000);
}

If you just need one random name, there's no need to create a list, of course.


In general, never use malloc in C++, it doesn't create objects, it just gives you raw memory.
If you must manually and dynamically create objects, use the following, in order of preference:

  1. Standard library containers like std::vector
  2. Smart pointers like std::unique_ptr
  3. Manual calls to new, new[], delete, delete[]

Avoid the last one at all costs, but if you really must do it manually, encapsulate the calls to new/delete in a RAII class that properly allocates and deallocates the storage. If you don't, you'll end up with memory leaks or double frees. Make sure that your wrapper satisfies the Rule of Five.

Why? Malloc/realloc/free don't mix well with the rest of the language. They only work for C-like types. New/delete work for all C++ types.

In everyday programming, needing a block of raw memory is very rare. Usually you want to dynamically allocate objects or arrays of objects, not raw memory.

malloc works for any type as far as I know.

It is just a personal preference. I either use the C style or the C++ style, I do not like mixing them.

Using the standard library would indeed be best, when available.

It doesn't, it only works for so-called implicit-lifetime types.
You cannot malloc a String or std::string object, for example, you must call new to actually create the object, just having raw memory is not sufficient.

From cppreference:

This function [malloc] does not call constructors or initialize memory in any way. There are no ready-to-use smart pointers that could guarantee that the matching deallocation function is called. The preferred method of memory allocation in C++ is using RAII-ready functions std::make_unique, std::make_shared, container constructors, etc, and, in low-level library code, new-expression.

That is true, no initialisation will be done.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.