不使用嵌套的 if 语句只打印改变的值

Print only changed values without the use of nested if statements

我有四个不同的传感器,并将它们记录的值存储在一个结构中。现在我想每分钟打印这些值。但只有与上次打印相比发生变化的值!

struct SensorData{
  uint8_t temp; //temperature
  uint8_t pres; //presure
  uint8_t hum; //humidity
  uint8_t fuel; //fuel
};

我用 15 个 ifs 解决了这个问题。但这有点难以阅读和调试。所以我很想知道是否有更好更优雅的方法来解决这个问题。

所有可能性的 table:如果值与之前的值不同则为 1,如果它们相同则为 0:

我现在是这样用ifs解决的:

if(storeData.temp != sensorData.temp && storeData.pres != sensorData.pres && storeData.hum != sensorData.hum && storeData.fuel == sensorData.fuel){
    //print case 1: temp,pres,hum
  }
  else{
    if(storeData.temp != sensorData.temp && storeData.pres != sensorData.pres && storeData.hum == sensorData.hum && storeData.fuel != sensorData.fuel){
      //print case 2: temp,pres,fuel
    }
    else{
      if(storeData.temp != sensorData.temp && storeData.pres != sensorData.pres && storeData.hum == sensorData.hum && storeData.fuel == sensorData.fuel){
        //print case 3: temp,pres,
      }else{
        if(storeData.temp != sensorData.temp && storeData.pres == sensorData.pres && storeData.hum != sensorData.hum && storeData.fuel != sensorData.fuel){
          //print case 4: temp,hum,fuel
        }else{
         ...

正如我提到的,我正在寻找一种无需使用 15 个 ifs 即可更优雅地解决此问题的方法。感谢您的帮助

我会用 4 ifs:

std::string output;
char delimiter = ',';

//Check if data changed
if (storeData.temp != sensorData.temp)
    output += std::to_string(sensorData.temp) + delimiter;
if (storeData.pres != sensorData.pres)
    output += std::to_string(sensorData.pres) + delimiter;
if (storeData.hum != sensorData.hum)
    output += std::to_string(sensorData.hum) + delimiter;
if (storeData.fuel != sensorData.fuel)
    output += std::to_string(sensorData.fuel) + delimiter;

//Check if nothing changed
if (output == "")
    ;//Skip using 'return'?

//Remove 'delimiter' from last case
output.erase(output.length() - 1, 1);

//Send 'output'
//....

您只能使用 4 个 if 语句。
分别检查每个变量的变化,在每个 if 块中使用 print 语句。

根据提到的约束,我没有找到任何你不应该这样做的理由。

如果要在单个打印语句中打印它们:
如上所述使用 4 个 if 语句,并使用 4 个变量来保存每个 if 语句的值。最后,打印成一行。

另一种方法是逐步构建 'printing string' 或 'number'(从一个空的 string 开始并在每个 if 语句中构建它)。

您可以使用数组来存储值,并使用循环来检查哪些数组元素已更改。 C中的粗略轮廓(可能包含错误,没有运行通过编译器):

#include <stdbool.h>
char *sensorNames[] = {"temp", "pres", "hum", "fuel"};
uint8_t sensorData[4];
uint8_t storeData[4];
int i;
bool first

while (1) {
  get_data(sensorData);
  first = true;
  for (i=0; i < sizeof(sensorData); i++) {
    if (sensorData[i] != storeData[i]) {
      // something changed
      if (!first) puts(", "); // add a comma if not first item in line
      printf("%s: %d -> %d", sensorNames[i], storeData[i], sensorData[i]);
      storeData[i] = sensorData[i]; // remember value
      first = false;
    }
  }
  if (!first) puts("\n"); // add a line feed if there were any changes
}

其他优势:添加第 5 个或第 6 个传感器是微不足道的:-)

您的 table 只是代表传感器的四位枚举。因此,您可能有四次比较并相应地调整结果的位:

#include <cstdint>

struct SensorData
{
    enum Index
    {
        Temperature = 3,
        Presure = 2,
        Humidity = 1,
        Fuel = 0
    };

    std::uint8_t temp; // temperature
    std::uint8_t pres; // presure
    std::uint8_t hum;  // humidity
    std::uint8_t fuel; // fuel
};

unsigned compare_sensors(const SensorData& a, const SensorData& b) {
    unsigned result = 0;
    result |= (a.temp != b.temp) << SensorData::Temperature;
    result |= (a.pres != b.pres) << SensorData::Presure;
    result |= (a.hum  != b.hum)  << SensorData::Humidity;
    result |= (a.fuel != b.fuel) << SensorData::Fuel;
    result = 15 - result; // adjust order
    return result;
}


#include <iostream>

int main()
{
    SensorData a = {};
    SensorData b = {};
    b.pres = 255;
    b.fuel = 255;
    std::cout << "Prssure/Fuel change is case " << compare_sensors(a, b) << ".\n";
}