Как реализовать обратное перечисление?

В основном я пытаюсь вывести строку на основе значения в массиве, следующий код — это то, что я придумал для достижения желаемого результата, но у меня есть ощущение, что есть лучший способ сделать это .

String day(int day) {
  if (day == 1) return "Sunday";      
  if (day == 2) return "Monday";
  if (day == 3) return "Tuesday";
  if (day == 4) return "Wednesday";
  if (day == 5) return "Thursday";
  if (day == 6) return "Friday";
  if (day == 7) return "Saturday";
  else return "Undefined";
}

void setup() {
  Serial.begin(57600);
  while (!Serial);
  Serial.println(day(1));
}

void loop() {
;
}

Это печатает "Воскресенье" в последовательном мониторе

Я буду признателен за любые советы по оптимизации этого кода, спасибо!

, 👍1

Обсуждение

Всего одна маленькая вещь, чтобы добавить ко всем ответам. Поскольку это «перечисление», я предлагаю заменить магическое число int на дружественное к рефакторингу enum., @Filip Franik


2 ответа


3

Мой метод использует класс __FlashStringHelper:

// Для удобства:
typedef const __FlashStringHelper *FlashString;


FlashString reverseEnum(int val) {
    switch (val) {
        case 0: return F("Option zero");
        case 1: return F("Option one");
        case 2: return F("Option two");
        default: return F("Invalid Enum");
    }
}

Теперь печатать так же просто, как:

Serial.println(reverseEnum(2));

Поскольку это "флэш-строка", функция print правильно перегружена и выполняет правильное чтение PROGMEM.

Конечно, вы можете назначить FlashString:

FlashString myString = reverseEnum(2);
Serial.println(myString);

Или, если вы не хотите использовать typedef, вы можете использовать необработанный тип:

const __FlashStringHelper *myString = reverseEnum(2);
Serial.println(myString);

Просто гораздо чище использовать typedef.

,

Спасибо за информацию, я действительно надеялся найти способ использовать перечисление вперед и назад без необходимости кодировать обратное., @H3xx1st

Возможно, вы могли бы создать что-то действительно ужасное и сложное со многими слоями макросов препроцессора, но это было бы неприятно и трудно для понимания. Так что не надо. ;), @Majenko


1

Я не эксперт, но полагаю, что что-то вроде этого сработает:

char* day(int day) {

  static char* dayName[7] = {"Sunday", "Monday", .... };

  if (day > 0 && day < 8) {
    return dayName[day-1];
  } 
  else
    return "Undefined";
  }
}

В любом случае, мне будет интересно узнать, почему это неправильно (-:

,

Да, массив строк char* C кажется лучше, чем длинный оператор switch. (проголосовали), @Duncan C

Указатели на строковые литералы должны быть const char*, а не char *., @Edgar Bonet

@EdgarBonet - Любопытно - в чем здесь преимущество const? Это стиль, скорость, память...?, @Jim Mack

Правильность. В C++ вам не разрешено изменять содержимое строкового литерала., @Edgar Bonet