structure types

I'm trying to sort of follow an example on creating structures and defining data types. Iv'e come up with this small program that i understand most of the program. The part i don't understand is why do i declare model of the type Cars in the class Other. why not just declare it in Cars instead? Why don't i have to specify a data type for model?

struct Cars {
  public:
    String name;
    unsigned long cost;
    Cars() : name("mycar"), cost(2222) {}
};

struct Other {
  Cars model[10];
  public:
} other;

void setup() {
  Serial.begin(9600);
}

void loop() {
  other.model[0].name = "car1";
  other.model[0].cost = 1000;
  other.model[1].name = "car2";
  other.model[1].cost = 2000;

  other.model[2].name = "car3";
  other.model[2].cost = 3000;
  other.model[3].name = "car4";
  other.model[3].cost = 4000;

  other.model[4].name = "car5";
  other.model[4].cost = 5000;
  other.model[5].name = "car6";
  other.model[5].cost = 6000;

  other.model[6].name = "car7";
  other.model[6].cost = 7000;
  other.model[7].name = "car8";
  other.model[7].cost = 8000;

  other.model[8].name = "car9";
  other.model[8].cost = 9000;
  other.model[9].name = "car10";
  other.model[9].cost = 10000;
  
  for (int num = 0; num < 10; num++) {
    Serial.println(other.model[num].name);
    Serial.println(other.model[num].cost);
  }
  delay(20000);
}

Well this is probably one of the worst ways of showing someone structures. There is more wrong then right, but lets deal with your question.

  1. Model is not referring to a model of car, it is an array of cars. Piss poor name for an array of cars.
  2. The structure Cars name, is silly, as the structure is describing one car.
  3. You are correct, if the Car object wanted to track model it would be the best place to store it
  4. You do not need a class that only contains an array of Cars, the other class is pointless.

Please do not read or use anymore examples from where this one came from.

Romonaga:
Well this is probably one of the worst ways of showing someone structures. There is more wrong then right, but lets deal with your question.

  1. Model is not referring to a model of car, it is an array of cars. Piss poor name for an array of cars.
  2. The structure Cars name, is silly, as the structure is describing one car.
  3. You are correct, if the Car object wanted to track model it would be the best place to store it
  4. You do not need a class that only contains an array of Cars, the other class is pointless.

Please do not ready anymore examples from where this one came from.

the example i was using as a reference to come up with this example i made can be found here. i kinda went my own way with it which is why it looks so bad.

So my next question is when i try to declare the array models in Cars without a data type the compiler gives me an error does not name a type. Why am i struggling to declare model in the Cars class. When i defined model in class Other i did not name data type but instead made it an object in type Cars? i think i have a miss understanding of type vs data type

This yields compiler error "model does not name a type,

struct Cars {
  public:
     model[10];
    String name;
    unsigned long cost;
    Cars() : name("mycar"), cost(2222) {}
}carsClass;



void setup() {
  Serial.begin(9600);
}

void loop() {
  carsClass.model[0].name = "car1";
  carsClass.model[0].cost = 1000;
  carsClass.model[1].name = "car2";
  carsClass.model[1].cost = 2000;

  carsClass.model[2].name = "car3";
  carsClass.model[2].cost = 3000;
  carsClass.model[3].name = "car4";
  carsClass.model[3].cost = 4000;

  carsClass.model[4].name = "car5";
  carsClass.model[4].cost = 5000;
  carsClass.model[5].name = "car6";
  carsClass.model[5].cost = 6000;

  carsClass.model[6].name = "car7";
  carsClass.model[6].cost = 7000;
  carsClass.model[7].name = "car8";
  carsClass.model[7].cost = 8000;

  carsClass.model[8].name = "car9";
  carsClass.model[8].cost = 9000;
  carsClass.model[9].name = "car10";
  carsClass.model[9].cost = 10000;
  
  for (int num = 0; num < 10; num++) {
    Serial.println(carsClass.model[num].name);
    Serial.println(carsClass.model[num].cost);
  }
  delay(20000);
}

model obviously does not name a data type. then what would be the correct way to define model array in Cars?

Well you need to be a bit more clear here. when I see model, I think model of car. So because I do not know what model is to represent it makes it hard for me to help.

In the code you presented, the error is correct, you have not provided a type for model. Should model be a string, and array of strings, should it be int an array of ints? You see you have not provided enough context.

You have provided a data type for name, and cost, so what data type represents model?

Romonaga:
Well you need to be a bit more clear here. when I see model, I think model of car. So because I do not know what model is to represent it makes it hard for me to help.

In the code you presented, the error is correct, you have not provided a type for model. Should model be a string, and array of strings, should it be int an array of ints? You see you have not provided enough context.

You have provided a data type for name, and cost, so what data type represents model?

What i'm trying to do is. Create a structure called cars. create an array inside the Cars structure called model. Then i want to give data to model like,

model[1].name="some string"
model[1].cost=integer

model[2].name="some string"
model[2].cost=integer

Then i can go back to the structure and access the data in the array like this,
carsClass.model[0].name = "car1";
Serial.println(carsClass.model[0].name);

I tried to declare model to be of data type "char" but then the compile complains,

error: request for member 'cost' in 'carsClass.Cars::model[num]', which is of non-class type 'char'

So im not sure what should i be using as a datatype fora array 'model' Why didn't i have to declare the data type when i placed model inside the "Other" structure?

If my guess of what you're trying to do is right, then your thinking is convoluted. You use a struct to group together items that belong to a larger object. In your case (I think) that object is a car -- a single car. The car has a model name and a cost (while we're at it, we're going to change from String to string so you don't get yelled at):

struct Car {
  char model[20];
  uint16_t cost;
};

So now, Car is a data type, but we have not yet defined any concrete objects that are Cars. If you have several Cars, it's logical to put them in an array:

Car myCars[] = {
  {"Mustang", 20000},
  {"Pinto", 100},
  {"Sunbird", 18000},
  {"Civic", 22000}
};

And, we can let the compiler do the counting of how many Cars we have:

const uint8_t numCars = sizeof(myCars) / sizeof(myCars[0]);

Putting it together, we can manipulate them like this:

struct Car {
  char model[20];
  uint16_t cost;
};

Car myCars[] = {
  {"Mustang", 20000},
  {"Pinto", 100},
  {"Sunbird", 18000},
  {"Civic", 22000}
};

void printCars();

const uint8_t numCars = sizeof(myCars) / sizeof(myCars[0]);

void setup() {
  Serial.begin(115200);
  delay(1000);
  printCars();

  strcpy(myCars[0].model, "Malibu");
  myCars[0].cost = 15000;

  strcpy(myCars[3].model, "Infinity");
  myCars[3].cost = 64000;

  Serial.println();
  printCars();
}

void loop() {
}

void printCars() {
  for (uint8_t i = 0; i < numCars; i++) {
    Serial.print(myCars[i].model);
    Serial.print(", $");
    Serial.println(myCars[i].cost);
  }
}

Serial Console Output:

Mustang, $20000
Pinto, $100
Sunbird, $18000
Civic, $22000

Malibu, $15000
Pinto, $100
Sunbird, $18000
Infinity, $64000

Thanks, I like how you manipulated the for loop with numCars but, what about the code i posted earlier even tho its not the best way to write something like that. why did it work when i declared Cars Timers[4] in class "Other" but not in cars. why don't it work in class Cars?

notsolowki:
why did it work when i declared Cars Timers[4] in class "Other" but not in cars. why don't it work in class Cars?

You mean like this?

struct Car {
  const char *name;
  unsigned int cost;

  static Car models[10];
};

Car Car::models[] = {
  {"Car1", 1000},
  {"Car2", 2000},
  {"Car3", 3000},
  {"Car4", 4000},
  {"Car5", 5000},
  {"Car6", 6000},
  {"Car7", 7000},
  {"Car8", 8000},
  {"Car9", 9000},
  {"Car10", 10000},
};

void setup() {
  Serial.begin(115200);
}

void loop() {
  for (Car &car : Car::models) {
    Serial.print(car.name);
    Serial.print(": $");
    Serial.println(car.cost);
  }
}

You cannot declare a struct that contains an instance of itself, that would be infinite recursion.
But you can make it static.

No i mean why does this work,

struct Cars {
  public:
  
    String name;
    unsigned long cost;
    Cars() : name("mycar"), cost(2222) {}
};

struct SomeRandomStructure {
  public:
  Cars model[10];
}sRs;


void setup() {
  Serial.begin(115200);
}

void loop() {
  sRs.model[0].name = "car1";
  sRs.model[0].cost = 1000;
  sRs.model[1].name = "car2";
  sRs.model[1].cost = 2000;
  sRs.model[2].name = "car3";
  sRs.model[2].cost = 3000;
  sRs.model[3].name = "car4";
  sRs.model[3].cost = 4000;
  sRs.model[4].name = "car5";
  sRs.model[4].cost = 5000;
  sRs.model[5].name = "car6";
  sRs.model[5].cost = 6000;
  sRs.model[6].name = "car7";
  sRs.model[6].cost = 7000;
  sRs.model[7].name = "car8";
  sRs.model[7].cost = 8000;
  sRs.model[8].name = "car9";
  sRs.model[8].cost = 9000;
  sRs.model[9].name = "car10";
  sRs.model[9].cost = 10000;
  for (int num = 0; num < 10; num++) {
    Serial.println(sRs.model[num].name);
    Serial.println(sRs.model[num].cost);
  }
  delay(20000);
}

but this dont,

struct Cars {
  public:
  Cars model[10];
    String name;
    unsigned long cost;
    Cars() : name("mycar"), cost(2222) {}
}cars;

struct SomeRandomStructure {
  public:
  
}sRs;


void setup() {
  Serial.begin(115200);
}

void loop() {
  cars.model[0].name = "car1";
  cars.model[0].cost = 1000;
  cars.model[1].name = "car2";
  cars.model[1].cost = 2000;
  cars.model[2].name = "car3";
  cars.model[2].cost = 3000;
  cars.model[3].name = "car4";
  cars.model[3].cost = 4000;
  cars.model[4].name = "car5";
  cars.model[4].cost = 5000;
  cars.model[5].name = "car6";
  cars.model[5].cost = 6000;
  cars.model[6].name = "car7";
  cars.model[6].cost = 7000;
  cars.model[7].name = "car8";
  cars.model[7].cost = 8000;
  cars.model[8].name = "car9";
  cars.model[8].cost = 9000;
  cars.model[9].name = "car10";
  cars.model[9].cost = 10000;
  for (int num = 0; num < 10; num++) {
    Serial.println(cars.model[num].name);
    Serial.println(cars.model[num].cost);
  }
  delay(20000);
}

and by work i mean what i think is 10 entries in model being updated with their own individual names and costs so to speak

Because the language syntax says so. C++ is a single pass compile, everything referenced after must be fully declared before.

notsolowki:
but this dont,

struct Cars {

public:
   Cars model[10];
   // ...
};

You tell the compiler: I define a "Cars" object as something that has 10 more "Cars" objects inside of it.
How is that supposed to work?

Okay so if i place it inside some other class and declare Cars model[] it automatically picks the datatype? void? so would i fully declare model inside the Cars class?

notsolowki:
Okay so if i place it inside some other class and declare Cars model[] it automatically picks the datatype? void?

A data type for what? The data type of "model" is "an array of Cars objects" (Cars[]).

notsolowki:
Okay so if i place it inside some other class and declare Cars model[] it automatically picks the datatype? void? so would i fully declare model inside the Cars class?

No, wherever you want to place your Car instances, that struct/class must see the full definition declaration of Car first.

arduino_new:
No, wherever you want to place your Car instances, that struct/class must see the full definition declaration of Car first.

so what am i missing in the definition of model? Show me how to properly define it please

Before you can create (instantiate) a "Car" object, the compiler must know what parts it's made of, and how much memory it has to reserve for it. You do this by writing down the declaration:

struct Car {
  const char *name;
  unsigned int cost;
};

You cannot create any "Car"s before the declaration is finished, i.e. before the closing bracket }.

notsolowki:
is this how?
Car model[10] = {car1,car2,car3,};

That's not a declaration, that's the instantiation of an array of ten "Car" objects.

none of this makes sense to me, can you please just show me in the code i posted how to what i'm trying to do

notsolowki:
so what am i missing in the definition of model? Show me how to properly define it please

Here you go:

#include <iostream>
#include <string.h>

struct Car {
   char name[20];
   int cost;
};

class CarOperator {
   public:
   Car models[10];
   CarOperator() : models {{"RedCar", 10},{"BlueCar", 20}} //initialize the array, you can add more initialization
   {
   }
   Car& operator[](int index) 
   {
      return models[index];
   }
};


int main()
{
    CarOperator carOp;
    std::cout << carOp[0].name << std::endl;
    strcpy(carOp[0].name, "YellowCar");
    std::cout << carOp[0].name << std::endl;
}

Note 1: The provided overload [] bracket is for ease of access the array. If you don't like/understand it. You could access your array as:

carOp.models[0].name;

Note 2: code is written for PC because it takes less effort to run. But it should run the same for Arduino once you replace the printing statements;and put code in main() in your setup()

notsolowki:
none of this makes sense to me, can you please just show me in the code i posted how to what i'm trying to do

Then please tell us in a clear way what it is you're trying to do?

PieterP:
Then please tell us in a clear way what it is you're trying to do?

Apparently i don't know what i'm trying to do

hopefully you can just tell by looking at this,

struct Cars {
public:
String name;
Cars model[10] // this dont work whats the right way to define this obvious array in the obvious class of Cars
unsigned long cost;
Cars() : name("mycar"), cost(2222) {}
}cars;