Basic Array help.

Folks,

I'm working on a clock that is programmed with mostly birthdays, but also some anniversaries, and a few RIPs for some special people that have passed. I have about 100 people so far but I'm new to programming so I used 100 if statements. I have yet to learn about arrays so I thought this would be a good opportunity for me to learn - hopefully I didn't pick a task too hard for someone of my skill level. My initial thought was to use a the following format.

Name, Month of Birth, Day of Birth, 1-3 (1 = Bday, 2 = Anniversary, 3 = RIP)

Below is my attempt at the code but it did not compile. Your thoughts about my approach or the error I'm getting below would be appreciated.

char birthdays[15,4] = {  { "Amanda",1,2,1},    // Name, Month, Day, 1=Bday  2=Anniversary  3=RIP
                          { "Amy",1,4,1 },
                          { "Bill",1,5,1 },
                          { "Bob",1,13,1 },
                          { "Carl",1,21,1 },
                          { "Dan",2,2,1 },
                          { "Diane",2,7,1 },
                          { "Edna",3,15,1 },
                          { "Frank & Lisa",5,20,2 },
                          { "George",6,18,3 },
                          { "Hank",7,2,1 },
                          { "Joan",8,13,1 },
                          { "Kim & Dan",9,13,2 },
                          { "Larry",10,13,1 },                          
                          { "Mary",11,17,1 } };

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
Serial.print(birthdays[0][0]);  // I want to print "Amanda"
}

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

Error.

Array:2:18: error: expected ']' before ',' token

char birthdays[15,4] = { { "Amanda",1,2,1}, // Name, Month, Day, 1=Bday 2=Anniversary 3=RIP

^

Array:2:19: error: expected unqualified-id before numeric constant

char birthdays[15,4] = { { "Amanda",1,2,1}, // Name, Month, Day, 1=Bday 2=Anniversary 3=RIP

^

/Users/tonyperry/Documents/Arduino/Array/Array.ino: In function 'void setup()':

Array:22:14: error: 'birthdays' was not declared in this scope

Serial.print(birthdays[0][0]);

^~~~~~~~~

exit status 1

expected ']' before ',' token

Also, I'm new to Arduinos and programing. What are some good basic books for someone like me, without very much experience.

Best,

Tony

You cannot mix data types in an array. All elements must be the same data type. Your "array" has a string and 3 integers (bytes).

You can mix data types in a struct. Google "arduino struct" for more information.

Here is your code using a struct

struct People
{
   char name[17]; // room for 16 characters and a NULL
   byte month;
   byte day;
   byte type;
};

// declare an array of structs
People birthdays[15] = {  { "Amanda",1,2,1},    // Name, Month, Day, 1=Bday  2=Anniversary  3=RIP
                          { "Amy",1,4,1 },
                          { "Bill",1,5,1 },
                          { "Bob",1,13,1 },
                          { "Carl",1,21,1 },
                          { "Dan",2,2,1 },
                          { "Diane",2,7,1 },
                          { "Edna",3,15,1 },
                          { "Frank & Lisa",5,20,2 },
                          { "George",6,18,3 },
                          { "Hank",7,2,1 },
                          { "Joan",8,13,1 },
                          { "Kim & Dan",9,13,2 },
                          { "Larry",10,13,1 },                         
                          { "Mary",11,17,1 } };

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
Serial.print(birthdays[0].name);  // I want to print "Amanda"
}

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

Output:

Amanda

You can probably get by without books. Any C++ tutorial on-line will likely be helpful. Just the first few sections will do - no need to learn how to write classes initially.

Also if/when you do get to multidimensional arrays, the syntax is not what you tried

int data[3][4];

is 12 integers in a 3 x 4 array. To refer to one the same syntax is used

int kk;
kk = data[2][1];

picks out one integer. Indices run from 0 to n-1; a three dimensional array would be like

int data[3][4][5];

here 60 elements in all.

HTH

a7

alto777:
Also if/when you do get to multidimensional arrays, the syntax is not what you tried

int data[3][4];

is 12 "int"s in a 3 x 4 array.

While these days no books are needed, I would still recommend

The C Programming Language

by Kernighan and Ritchie

for its straight ahead exposure to all the beauty and otherwise of C and much good advices on programming.

a7

Thanks all.

@groundFugus Thank you. I checked out the link on struct that you sent and a tear came to my eye. Like a more confusing version on arrays.

This hobby always takes you in different directions. Always something to learn, or figure out. It's interesting. I have learned a lot. And I've built some interesting projects along the way. Especially with the help of this forum. My wife, however, remains completely unimpressed with anything I've accomplished. "Your gizmos," she says.

Here is an example of getting the data from the struct for one name.

struct People
{
   char name[17]; // room for 16 characters and a NULL
   byte month;
   byte day;
   byte type;
};

// an array of structs
People birthdays[15] = {  
   { "Amanda", 1, 2, 1}, // Name, Month, Day, 1=Bday  2=Anniversary  3=RIP
   { "Amy", 1, 4, 1 },
   { "Bill", 1, 5, 1 },
   { "Bob", 1, 13, 1 },
   { "Carl", 1, 21, 1 },
   { "Dan", 2, 2, 1 },
   { "Diane", 2, 7, 1 },
   { "Edna", 3, 15, 1 },
   { "Frank & Lisa", 5, 20, 2 },
   { "George", 6, 18, 3 },
   { "Hank", 7, 2, 1 },
   { "Joan", 8, 13, 1 },
   { "Kim & Dan", 9, 13, 2 },
   { "Larry", 10, 13, 1 },
   { "Mary", 11, 17, 1 }
};

void setup()
{
   // put your setup code here, to run once:
   Serial.begin(9600);
   //Serial.print(birthdays[0].name);  // I want to print "Amanda"

   // get date time and type for George
   getNameData("George");
}

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

void getNameData(const char* thename)
{
   for (unsigned int n = 0; n < sizeof(birthdays) / sizeof(birthdays[0]); n++)
   {
      if (strcmp(thename, birthdays[n].name) == 0)
      {
         Serial.println();
         Serial.print("Name  ");
         Serial.print(birthdays[n].name);
         Serial.print("  Month  ");
         Serial.print(birthdays[n].month);
         Serial.print("  Day  ");
         Serial.print(birthdays[n].day);
         Serial.print("  Type  ");
         switch (birthdays[n].type)
         {
            case 1:
               Serial.print("Birthday");
               break;
            case 2:
               Serial.print("Anniversary");
               break;
            case 3:
               Serial.print("RIP");
               break;
            default:
               Serial.print("Invald type");
               break;               
         }
         break;
      }
   }
}

Output:

Name  George  Month  6  Day  18  Type  RIP

This is the same application as in your previous thread, and a continuation of its discussion. It is not necessary to start a new thread for each new programming problem that you have with a project - it's preferable to just keep one thread going to make it easier for people to see the context and get some background information that you would often omit from a new post.

@aarg Ok. Sorry about that. I wasn't sure.

@groundFungus Could you explain this? It's confusing me.

   for (unsigned int n = 0; n < sizeof(birthdays) / sizeof(birthdays[0]); n++)
sizeof(birthdays) / sizeof(birthdays[0])

The number of elements in the array "birthdays"

Simpler / different

for (auto & birthday :  birthdays)
   {
      if (strcmp(thename, birthday.name) == 0)
      {
         Serial.println();
         Serial.print("Name  ");
         Serial.print(birthday.name);
         Serial.print("  Month  ");
         Serial.print(birthday.month);
         ...Yadda yadda

OK. I've got a lot to learn.

In my case, I assume I would take the approach of looping through the "records" looking for instances where there is a match to today's date. Correct?

sizeof(birthdays)

The number of bytes that the birthdays array occupies (300).

sizeof(birthdays[0]

The number of bytes occupied by one element of the birthdays array (20).

So divide the number of bytes in the whole array by the bytes in one element give the number of elements (structs or records) in the array (15).
There are 15 structs (records) in the birthdays array of structs.

I do it that way so you can add to the number of structs in the array without messing with the for loop. The for loop automatically knows how many structs (records) there are.

In my case, I assume I would take the approach of looping through the "records" looking for instances where there is a match to today's date. Correct?
You could do that. Sort out the records with the right month and then sort for the day.

Ok. I see where 15 comes from. And I understand 15 x 20 = 300. How did you arrived at 20 for the number of bytes occupied by one element of the array? Is that easily explained/demonstrated?

struct People
{
   char name[17]; // room for 16 characters and a NULL
   byte month;
   byte day;
   byte type;
};

17 + 1 + 1 + 1

Supposed I used a 20x4 display. Would I then change the code to?

struct People[color=#222222][/color]
{[color=#222222][/color]
   char name[21]; // room for 20 characters and a NULL[color=#222222][/color]
   byte month;[color=#222222][/color]
   byte day;[color=#222222][/color]
   byte type;[color=#222222][/color]
};

And it that's the case, then would the total number of bytes be 360 (24 x 15)?

Sorry...

struct People
{
   char name[21]; // room for 20 characters and a NULL
   byte month;
   byte day;
   byte type;
};

The point of using the "sizeof(x) / sizeof (x[0])" construct is that you don't care.
Or you shouldn't.

What you should care about is you can't store a 20 character string in 20 bytes
You need 21 bytes