У меня каверзный, но интересный вопрос.Держитесь там!
Давайте предположим, что я пишу встроенный код, и я нахожусь в системе, где я должен хранить значения в 16-битном формате без знака, чтобы быть совместимым с другими системами.Некоторые значения имеют десятичную часть, но, к счастью, я заранее знаю положение разделителя (фиксированная точка).
Теперь давайте рассмотрим эту структуру:
typedef struct{
// pointer to a function that computes the "real" value
float (*getRealValue)(void);
// pointer to a function that computes a "stringified" value
bool (*getCustomString)(char *);
} var_info_t;
И давайте объявим одну переменную var1Это температура:
uint16_t var1 = 1530; // means 15.3°C
float var1_toFloat(void){ return (float)var1/100; } // should return 15.3
var_info_t var1_info = { .getRealValue = var1_toFloat, .getCustomString = NULL };
и другая переменная var2, которая больше похожа на логическое значение:
uint16_t var2 = 1; // means Enabled
bool var2_toString(char* buffer){ // should write "Enabled"
if(buffer) sprintf(buffer, "%s", var2 ? "Enabled" : "Disabled");
return true;
}
var_info_t var2_info = { .getRealValue = NULL, .getCustomString = var2_toString };
Теперь я хочу отобразить эти значения вместе на экране,с некоторым необычным форматированием, которое может меняться в зависимости от того, где эти значения записаны на экране.
(мне просто нужно позвонить TEXT_SetText(int widget_id, char* text)
, чтобы обновить мои виджеты с графическим интерфейсом.)
Что я хочу сделать, так это создать «обертку» для TEXT_SetText () вот так ...
static char text[128], buf[2][32];
#define GET_VAR_AUTO(var_info, i) \
((var_info.getCustomString != NULL && var_info.getCustomString(buf[i])) ? buf[i] : \
(var_info.getRealValue != NULL ? var_info.getRealValue() : 0))
void my_TEXT_SetText(int widget_id, char* format, var_info_t a, var_info_t b){
snprintf(text, sizeof(text), format, GET_VAR_AUTO(a, 0), GET_VAR_AUTO(b, 1));
TEXT_SetText(widget_id, text);
}
... так, чтобы вызывать my_TEXT_SetText(0, "Regulator is %s at %.1f\260C", var2_info, var1_info);
будет отображать Regulator is Enabled at 15.3°C
внутри моей коробки.
Настоящее преимущество в том, что вы можете обновлять текст в режиме реального времени просто периодически вызывая эту функцию из «где угодно» (не «ничего не зная» оПеременные или их значения).Также вы можете просто увеличить количество переменных внутри одного и того же текста, увеличив число snprintf
аргументов.
Проблема: макрос GET_VAR_AUTO не синтаксически корректен, поскольку он смешивает char*
с buf[i]
и float
с getRealValue()
в возможных результатах троичного оператора:
ошибка: несоответствие типов в условном выражении
НО, зная, что sprintf
- это переменная функция , которая обрабатывает свои аргументы в соответствии с типами, указанными в строке формата (% f,% s, ... благодаря va_arg()
функция), есть ли способ найти общий абстрактный тип для троичного оператора , который будет принят sprintf
?
Я много чего пробовал, но не могузаставить char*
и float
работать одновременно.
(К сожалению, я использую C, а не C ++)