Compare and get maximum values in array of struct

Hi there, I stuck at finding the maximum values in array of a struct..

typedef struct {
  char messageType[2];
  char sID[3] = {0} ;  // key1
  char dID[3];
  char route1[3];
  char route2[3];  //key2
  char RSSI1[5];
  char RSSI2[5]; 
  char hops[2];
  
} MyDataSet_t ;

MyDataSet_t myDatatable[MAX_SENDERS] ;
char dID1 =  myDatatable[0].dID;                          //error occurs from here until hops there..
char min_routes1[3]=  myDatatable[0].routes1;   
char min_routes2[3] = myDatatablle[0].routes2;
char min_RSSI1[5] = myDatatable[0].RSSI1;
char min_RSSI2[5] = myDatatable[0].RSSI2;
char min_hops[2] =  myDatatable[0].hops;

.
.
.

if ((myDatatable[i].pRSSI<=min_pRSSI))
{
      min_pRSSI = myDatatable[i].pRSSI;
      min_hops = myDatatable[i].hops;
     dID1 =  myDatatable[i].dID;    
      routes1 =  myDatatable[i].routes1; 
      routes2 = myDatatable[i].routes2;
}

I wanted to compare with each lines in the struct table..the error I gt: array must be initialized with a brace-enclosed initializer..Pls help!

Hi @stephanie9

do a bit of effort and take into account what was discussed in the other posts please or I'll have to agree with the others that you are trolling and not listening...

  • post a complete code that you can compile. (a minimum example)
  • though we had discussed that RSSI would be better as numbers than text?
  • thought we said typedef is useless ?

char dID1 = myDatatable[0].dID; //error occurs from here until hops there..

in your code, what is the type of dIDin the struct ?
what's the type of dID1 when trying to do the assignment that fails ?

if ((myDatatable[i].pRSSI<=min_pRSSI))

there is no pRSSI value in the struct, we have no clue what min_pRSSI is...

long story short, please provide a fully self contained working example.

alright, sry it was my mistake..

struct {
  char messageType[2];
  char sID[3] = {0} ;  // key1
  char dID[3];
  char routes1[3];
  char routes2[3];  //key2
  int16_t RSSI1[5];
  int16_t RSSI2[5]; 
  int16_t pRSSI[5];
  char hops[2];
  
} MyDataSet_t ;

MyDataSet_t myDatatable[MAX_SENDERS] ;   //correction: max_senders should be assigned as 5
char dID1[3] =  myDatatable[0].dID;
char routes1[3]=  myDatatable[0].routes1;
char routes2[3] = myDatatable[0].routes2;
char min_RSSI1[5] = myDatatable[0].RSSI1;    // how do I assign to the array[0] then if they are changed to int16_t?
char min_RSSI2[5] = myDatatable[0].RSSI2;
char min_pRSSI[5] = myDatatable[0].pRSSI;   // are the addition of RSSI1 and RSSI2
char min_hops[2] =  myDatatable[0].hops;

void dispaly() {
 
  for ( uint16_t i = 0 ; i < MAX_SENDERS ; i++ ) {
    
    sprintf( buf , "%s %s %s %s %s %s \n"  ,
             myDatatable[ i ].messageType ,
             myDatatable[ i ].sID ,
             myDatatable[ i ].dID ,
             
             myDatatable[ i ].routes1 ,
             myDatatable[ i ].hops,
             myDatatable[ i ].pRSSI 
           );
    Serial.print( buf ) ;
    snprintf(myDatatable[i].pRSSI , 5 , "%i" , pRSSI);
  
     if ((myDatatable[i].pRSSI<=min_pRSSI))   //comparison starts here
{
      min_pRSSI = myDatatable[i].pRSSI;
     dID1 = myDatatable[i].dID;
      min_hops = myDatatable[i].hops;
      routes1 =  myDatatable[i].routes1;  // they are to be used to send data back later
      routes2 = myDatatable[i].routes2;
}
  }
}


because the message.messageType in your code is kind of confusing for me.. and I didn't think the post can be continued discussing anymore..so I thought of using this instead.. and I tried to convert it back to integer to add them up before converting them back into string using snprintf.. but ya.. it is not as easy as expected.. so for the message.messageType way you using, is directly assigning the data into the struct, am I correct? then do you mind to share how do I look back the table and do the comparison as above, which I attempt to do..?

and to help (once more) here is a self contained example extracting min & max from an array of struct

struct t_demo {
  int v1;
  int v2;
} myDatatable[] = {{10, 20}, {12, 22}, {150, 25}, {4, 2}, {0, -36}, {12, 120}};
const size_t databaseCount = sizeof myDatatable / sizeof myDatatable[0];

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

  size_t indexMin = 0, indexMax = 0;

  // get min and max entries based on v1
  for (size_t i = 1; i < databaseCount; i++) {
    if (myDatatable[i].v1 > myDatatable[indexMax].v1) indexMax = i;
    if (myDatatable[i].v1 < myDatatable[indexMin].v1) indexMin = i;
  }

  Serial.print("Min / v1: {");
  Serial.print(myDatatable[indexMin].v1);
  Serial.print(", ");
  Serial.print(myDatatable[indexMin].v2);
  Serial.println("}");

  Serial.print("Max / v1: {");
  Serial.print(myDatatable[indexMax].v1);
  Serial.print(", ");
  Serial.print(myDatatable[indexMax].v2);
  Serial.println("}");

  // get min and max entries based on v2
  for (size_t i = 1; i < databaseCount; i++) {
    if (myDatatable[i].v2 > myDatatable[indexMax].v2) indexMax = i;
    if (myDatatable[i].v2 < myDatatable[indexMin].v2) indexMin = i;
  }

  Serial.print("Min / v2: {");
  Serial.print(myDatatable[indexMin].v1);
  Serial.print(", ");
  Serial.print(myDatatable[indexMin].v2);
  Serial.println("}");

  Serial.print("Max / v2: {");
  Serial.print(myDatatable[indexMax].v1);
  Serial.print(", ");
  Serial.print(myDatatable[indexMax].v2);
  Serial.println("}");
}

void loop() {}

work from there and provide suitable code for your case (that we can compile and test).

sry but I don't really understand this..

and for only pRSSI will be used to compared with each other , and the particular line will be chosen to be used later on, which I am not showing the code here(I guess I am able to do this), that's why I only use pRSSI to compare, then just assign other variable with the variables in the particular line..

sizeof is an operator returning the number of bytes used to represent a type or a variable

So

  • sizeof myDatatable is the number of bytes used to represent the full array of structures
  • sizeof myDatatable[0] is the number of bytes used to represent the first entry

so if you divide the total size of the array by the size of one element of the array (they all have the same size) you get the number of entries in the array ➜ databaseCount will be 6

so i have to do that instead of assigning initial value for any lines in the array?
like:

char dID1[3] =  myDatatable[0].dID;  // where error starts here
char routes1[3]=  myDatatable[0].routes1;
char routes2[3] = myDatatable[0].routes2;

because that's how I understand the way, by reading other similar posts..

No... you use strlcpy() or strcpy() to copy cStrings. You've seen that before.

char min_RSSI[5] ;
strcpy( min_RSSI,  myDatatable[ 0 ].pRSSI ) ;   // assigning initial value in any lines of the table

do you mean this? but I gt error again for the second line....

that should work unless there is something I don't see because it's a snippet...

Anyway, because you have struct, you can do

MyDataSet_t tmpData = myDatatable[0];

then everything is copied in one go, you duplicated myDatatable[0]into tmpData (this works on struct, it does not work on arrays. but if the array is within the struct then it's OK, as any other simple datatype)

that's how I did for all, so should be the same for other variables...

so my code should be

MyDataSet_t tmpData = myDatatable[0];
char min_RSSI[5];
strcpy(min_RSSI,tmpData.RSSI);
//or strlcpy version:

strlcpy(min_RSSI,tmpData.RSSI, sizeof min_RSSI);

//adding up

for ( uint16_t i = 0 ; i < MAX_SENDERS ; i++ ) {
    
    sprintf( buf , "%s %s %s %s %s %s \n"  ,
             myDatatable[ i ].messageType ,
             myDatatable[ i ].sID ,
             myDatatable[ i ].dID ,
             
             myDatatable[ i ].routes1 ,
             myDatatable[ i ].hops,
             myDatatable[ i ].RSSI 
           );
    Serial.print( buf ) ;
    snprintf(myDatatable[i].RSSI , 5 , "%i" , RSSI);
  
     if ((myDatatable[i].RSSI<=min_RSSI))   //comparison starts here
{
      min_pRSSI = myDatatable[i].pRSSI;
     dID1 = myDatatable[i].dID;    //assuming they are assigned like min_RSSI
      min_hops = myDatatable[i].hops;
      routes1 =  myDatatable[i].routes1;  // they are to be used to send data back later
      routes2 = myDatatable[i].routes2;
}
  }
}

am I correct?

that would work. But do you need min_RSSI? can't you just use tmpData to hold the min and the rest of the structure?

Best probably would be to study my sample code rather than keep on with you memory costly idea....
You can see I did not duplicate any structure, I just identified the Index of the structure holding the min value.
That's how you should proceed.
once you have identified the location of the min struct, if you want to duplicate it into a variable, just do the struct assignment.

Sry I don't get waht you mean here..

:sob: :sob: I was kind of panic and not able to be calm down to read.. sry.. my fault.

I am sorry, I am NO LONGER looking at code I can't compile.

As said now multiple times. when you want to do something put the big code away and create a small example you can focus on outside the rest of the code.

Once you've solved your problem in the small example, you apply that to your real code.

it's past bed time here, so I let you understand the code with just one piece of advice that we already discussed:
➜ You can't compare strings... if ((myDatatable[i].RSSI<=min_RSSI))is wrong, you compare numbers... (remember strtol() please ? I spent enough time explaining it...)

good luck

1 Like

Alright.. I will spend time to study back all of these you have been explained earlier.. thanks man!