[Solved] Sort Algorithm for two bitfields in a struct.

I have an array of event records, each containing a start time element in hours and minutes and various other bit elements. I want to sort the array from earliest time of day to latest. Since midnight is a valid time, 0 hours, 0 minutes, and empty record will contain the hour value of 31 and a minute value of 0 and I have confirmed this is true. See the code below.

void swapEvents(bellEventStruct* pMinTime, bellEventStruct* pMinPlace) {
  bellEventStruct tempEvent = *pMinTime;
  *pMinTime = *pMinPlace;
  *pMinPlace = tempEvent;
}

void refreshEvents() {
  eventIndex = 0;// stops any iterations of the list until it has been sorted and counted.
  //first sort events by time
  unsigned char i, j, x;
  for(i = 0; i < 49; i++) {// indexes through sorted)
    x = i;// start at position 0
    for(j = i + 1; j < 50; j++) {//indexes through unsorted
      if(userNTPSettings.bellEvent[j].startHour <= userNTPSettings.bellEvent[x].startHour) {
        if(userNTPSettings.bellEvent[j].startMinute < userNTPSettings.bellEvent[x].startMinute) {
          x = j;
          swapEvents(&userNTPSettings.bellEvent[x], &userNTPSettings.bellEvent[i]);
        }
      }
    }
  }
  //second count events
  x = 0;
  for(unsigned char i = 0; userNTPSettings.bellEvent[i].startHour < 24; i++)
    x++;
  eventIndex = x;
  eventRecordsShown = (eventIndex < 10) ? 10: eventIndex;
}

I am calling this function where I need to… everything appears to be working except the sort function.

You’ll want to swap them if userNTPSettings.bellEvent[j].startHour is less than userNTPSettings.bellEvent[ x].startHour, regardless of how startMinute compares between the two.

        if(userNTPSettings.bellEvent[j].startHour < userNTPSettings.bellEvent[x].startHour ||
           (userNTPSettings.bellEvent[j].startHour == userNTPSettings.bellEvent[x].startHour &&
            userNTPSettings.bellEvent[j].startMinute < userNTPSettings.bellEvent[x].startMinute)) {
            swapEvents(&userNTPSettings.bellEvent[j], &userNTPSettings.bellEvent[i]);
        }

christop:
You’ll want to swap them if userNTPSettings.bellEvent[j].startHour is less than userNTPSettings.bellEvent[ x].startHour, regardless of how startMinute compares between the two.

        if(userNTPSettings.bellEvent[j].startHour < userNTPSettings.bellEvent[x].startHour ||

(userNTPSettings.bellEvent[j].startHour == userNTPSettings.bellEvent.startHour &&
           userNTPSettings.bellEvent[j].startMinute < userNTPSettings.bellEvent.startMinute)) {
           swapEvents(&userNTPSettings.bellEvent[j], &userNTPSettings.bellEvent[i]);
       }

Perfect!! works like a charm.

int timeJ = userNTPSettings.bellEvent[j].startHour * 60 + userNTPSettings.bellEvent[j].startMinute;
int timeX = userNTPSettings.bellEvent[x].startHour * 60 + userNTPSettings.bellEvent[x].startMinute;
if (timeJ < timeX) {
  swapEvents(&userNTPSettings.bellEvent[j], &userNTPSettings.bellEvent[i]);
}

In most applications I feel you are on a hiding to nothing storing dates/times as individual components. It’s almost always more hassle than it is worth. You can’t easily compare them, or add/subtract intervals, and to copy them you have a multiple fields to move around.

Meanwhile if they are stored as a single ordinal time stamp integer, all those operations become very simple. The only difficult part comes when you need to display them. In which case it is very easy to split the ordinal value out into its individual components. Generally this only needs to be done in one place in your code (or you can write a common routine to do the formatting).

If you have access to the standard library (on an ESP8266 or ARM, for example, or using a third-party library on AVR), it’s easiest to use std::sort, and define the comparison operator on your structs. You can simply tie the hour and minutes together as a tuple and compare them lexicographically:

#include <algorithm>
#include <tuple>

struct bellEventStruct {
  unsigned char startHour : 5;
  unsigned char startMinute : 6;
  // ...
};

// Define the "less than" operator for your struct.
bool operator<(const bellEventStruct a, const bellEventStruct b) {
  // Lexicographically compare the tuples (hour, minute)
  return std::tie(a.startHour, a.startMinute) <
         std::tie(b.startHour, b.startMinute);
}

bellEventStruct events[49];

void setup() {
    std::sort(std::begin(events), std::end(events));
    
    for (auto const &ev : events) {
        Serial.print(ev.startHour);
        Serial.print(':');
        Serial.println(ev.startMinute);
    }
}

void loop() {}

Full working example: Compiler Explorer

Pieter

Thank you for the additional methods.