在 C++ 中循环数组时访问结构 属性

Access to struct property while looping array in C++

我在遍历结构数组时遇到问题。

我有这个结构:

struct sensor
{
  float data = 0;
  bool status = false;
  Idx idx; //enum
  SensorType type; //enum
};

它包含一些适用于我的 arduino 的传感器。

所以为了发送我从他们那里收到的数据,我想在循环中使用传感器阵列。

这是我的数组定义:

sensor sensors[] = {light, pressure, pressureHpa, temperature, humidity, temperatureOut, humidityOut};

最后,我想遍历这个数组并调用一些方法,但是当我尝试按索引访问任何传感器时,我得到所有属性的零值。

  for (unsigned int i = 0; i < sizeof(sensors) / sizeof(sensor); i++)
  {
    Serial.print("type:");
    Serial.print(sensors[i].type);
    Serial.print(" sens.idx:");
    Serial.print(sensors[i].idx);
    Serial.print(" sens.data:");
    Serial.print(sensors[i].data);
    Serial.print(" sens.status:");
    Serial.print(sensors[i].status);
    Serial.println();
  }

在这个循环中,我得到如下输出:

type:0 sens.idx:0 sens.data:0.00 sens.status:0
type:0 sens.idx:0 sens.data:0.00 sens.status:0
type:0 sens.idx:0 sens.data:0.00 sens.status:0
type:0 sens.idx:0 sens.data:0.00 sens.status:0
type:0 sens.idx:0 sens.data:0.00 sens.status:0
type:0 sens.idx:0 sens.data:0.00 sens.status:0
type:0 sens.idx:0 sens.data:0.00 sens.status:0

但是,当我像这样直接访问我的任何结构时:

Serial.print("type:");
Serial.print(pressure.type);
Serial.print(" pressure.idx:");
Serial.print(pressure.idx);
Serial.print(" pressure.data:");
Serial.print(pressure.data);
Serial.print(" sens.status:");
Serial.print(pressure.status);
Serial.println();

我得到:

type:3 pressure.idx:13 pressure.data:0.00 sens.status:1

创建结构数组时:

sensor sensors[] = {light, pressure, pressureHpa, temperature, humidity, temperatureOut, humidityOut};

这会为您用来制作列表的每个结构创建一个副本。您要么必须使用指针数组:

sensor* sensors[] = {&light, &pressure, &pressureHpa, &temperature, &humidity, &temperatureOut, &humidityOut};

或者您必须创建自己的 class,存储对它们的引用:

class SensorArray {
    sensor** arr = nullptr;
    size_t count = 0; 
   public:
    size_t size() const {
        return count; 
    }
    // Default-construct it
    SensorArray() = default;

    // Make a copy of the SensorArray 
    SensorArray(SensorArray const& source)
      : arr(new sensor*[source.size()])
      , count(source.size())
    {
        std::copy_n(source.arr, source.count, arr);
    }

    // Move-construct SensorArray
    SensorArray(SensorArray&& source)
      : arr(source.arr)
      , count(source.count)
    {
        source.arr = nullptr; 
        source.count = 0; 
    }

    template<class T...>
    SensorArray(T&... sensors)
      : arr(new sensor*[] { &sensors... }) // Initialize arr
      , count(sizeof...(sensors))          // Initialize count
    {} // Constructor is empty because we already initialized stuff

    SensorArray& operator=(SensorArray const& source) {
        if(this == &source) return *this;

        SensorArray s = source;
        swap(s);
        return *this; 
    }

    // Copy-and-swap idiom
    // This automatically handles the case of self-assignment
    SensorArray& operator=(SensorArray&& source) {
        SensorArray s = std::move(source);
        swap(s);
        return *this;
    }
    sensor& operator[](int index) const {
        return *arr[index];
    }

    ~SensorArray() {
         delete[] arr;
    }
    void swap(SensorArray& other) {
        std::swap(arr, other.arr);
        std::swap(count, other.count);
    }
};

此 class 将按您的代码中的预期工作,因为它会为每个传感器存储一个 reference,而不是一个副本:

SensorArray sensors { light, pressure, pressureHpa, temperature, humidity, temperatureOut, humidityOut };

  // sensors will update correctly
for (unsigned int i = 0; i < sensors.size(); i++)
{
    Serial.print("type:");
    Serial.print(sensors[i].type);
    Serial.print(" sens.idx:");
    Serial.print(sensors[i].idx);
    Serial.print(" sens.data:");
    Serial.print(sensors[i].data);
    Serial.print(" sens.status:");
    Serial.print(sensors[i].status);
    Serial.println();
}

light 已定义并保留其默认值。

sensor sensors[] = {light, pressure, pressureHpa, temperature, humidity, temperatureOut, humidityOut};

light 复制到 sensors[0]。这意味着 sensors[0] 包含与 light 相同的数据,但与 light 不同。稍后当代码为 light 赋值时,sensors[0] 的副本保持不变。

选项 1

舍弃light和朋友。添加命名传感器的枚举类型

enum sensor_names
{
    LIGHT, // will be 0
    PRESSURE, //will be 1
    ...
    NR_SENSORS // must be last. Used to size the array and for loop terminators
};

并使sensors成为一个正确大小的简单数组

sensor sensors[NR_SENSORS];

如果可用,请随意使用 std::array and the smarter enums of modern C++。我不了解 Arduino 可用和不可用的内容,因此我坚持使用基本的 C 样式数组和 enums。如果您有更好的工具,请使用它们。

然后访问 light 作为 sensors[LIGHT];

选项 2

使 sensors 存储指针并相应地更改访问。

sensor * sensors[] = {&light, &pressure,  .... };

我更喜欢第一个选项。没有重复,并且将项目放置在数组中错误位置的可能性较低。