Можно ли работать со Struct как с массивом?
- Войдите на сайт для отправки комментариев
Чт, 30/01/2014 - 13:36
Здравствуйте, задача такая - опрашивать датчики в соотв. с заданными интервалами (для каждого интервал свой).
текущие значения датчиков храняться в структуре Current (13 элементов),
Каждый из элементов думаю сделать массивом, чтобы хранить данные о времени последнего обновления и интервале.
Чтобы не расписывать снова для каждого датчика идея была перебирать все элементы структуры в цикле - подобно массиву. Возможно ли это?
Представляю себе это примерно так:
typedef struct Data {
float temp1 [3]{0,2,0};
float hum1 [3]{0,2,0};//0-значение влажности, 2 - интервал проверки в секундах, 0- время последнего обновления.
float temp2 [2]{0,3,0};
float temp3 [2]{0,3,0};
float temp4 [2]{0,2,0};
float hum2 [2]{0,2,0};
int hum3 [2]{0,3,0};
boolean lampSens [3]{0,600,0};
int Hight [1]{1200,1250};//это не датчики, эти данные нужно передавать только если они изменились. 1200 - текущее, 1250-предыдущее.
int fanPwr[1]{150,255];
int compPwr [2]{0,30,0};
boolean filterSt [1] {1,1};
boolean doorSt [2]{0,2,0};
}Current;
void dataRead()
{
for (int i=0 i>=12 i++){
int j=Current[i].lenght //пробуем перебрать структуру и узнаем длину массива элемента
if (j==2){ //если массив из 3х элементов
double t=millis(); //прошло времени
if (t-Current[i][2]>=Current[i][1]){ //если пора обновлять
dataCheck(Current[i]); //обновляем значение этого элемента.. вот только мы же не знаем тип данных?!
Сurrent[i][2]=millis(); //,обнуляем счетчик
}
else if (j==1){ //если массив из двух
if(Current[i][0]!=Current[i][1]){ //если данные отличаются
Serial.println(Current[i][0]); //отправляем данные
Current[i][1]=Current[i][0]; //обновляем
}
}
}
}
}
Вобщем в таком виде код не работает, но думаю мысль моя понятна..
Еще смущают конечно типы.. Millis нужно записывать в Double, а элемент структуры может быть определен как boulean или int и как тогда быть?
Мысль понятна но такой подход ошибочен в принципе. Структура создатеся для того, чтобы логически объеденить несколько элементов в один, но это не массив!
Что вам мешает создать массив массивов если на то пошло? Просто и удовлетворить ваши потребности.
ТОже подумал об этом, но сталкиваюсь с проблемой: массив массивов может быть только однотипным насколько я понимаю.
т.е.
float tempAir[2]; int compPwr[2]; boolean filter [1]; param[]={tempAir,compPwr,filter};так сделать не получится, потому что какой тип массиву param не задавай - жалуется что нельзя преобразовать Float, int и boolean в этот тип.. Структура как раз позволяет объединять разнотипные данные.
А так Стракт можно было бы объявить и после и прописать в него значения уже определенных массивов.
Массив структур.
struct Data { ... uint8_t value; ... }; Data array[3] = { // Здесь инициализируются данные, если нужно { данные первого датчика}, { данные второго датчика}, { данные третьего датчика}, }; ... for( i =0; i < 3; ++i ) { Data &arr = array[i]; Serial.print( i ); Serial.print( "Value = " ); Serial.println( arr.value ); } ...Поддержу предыдущий пост.
Спасибо,
Компилится, но не работает.
Я так понимаю, что в struct я записываю все те элементы которые были в моем примере, с их типами. А зачем включать вот это: uint8_t value; ? что это дает?
Data array[3] - мы создаем массив структур.. может я ошибаюсь, но в таком случае каждый элемент массива будет представлять экземпляр структуры, а потом в этой конструкции мы задаем значения,я так понимаю те значения которые я задавал как массив для каждого элемента структуры. Вроде получается уже трехмерный массив, но компилятор не ругается.. Вобщем эта часть ускользает от понимания.
Data &arr = array[i]; - Здесь я так понимаю происходит создание ссылки на созданный ранее массив.
Честно сказать не понимаю что мы должны получить в итоге... Скомпилированный код не выдает вообще ничего, ни один из Serial.println не выводится в терминал.
struct Data { uint8_t value1_1; uint8_t value1_2; uint8_t value1_3; }; Data array[3] = { // Здесь инициализируются данные, если нужно {1,2,3 }, {4,5,6}, {7,8,9} }; int main() { for (int i=0; i<3; ++i ) { Data &arr = array[i]; Serial.println("Array element = " + i ); Serial.println( "Value_1 = " + arr.value1_1); Serial.println( "Value_2 = " + arr.value1_2); Serial.println( "Value_3 = " + arr.value1_3); }; }kaaKAA777
... видимо я что-то не догоняю. Точно как есть вставляю ваш код - он компилится без ошибок замечательно, но в Сериал порт не выводит вообще ничего! должен же эти цыфры выводить 1-9, а ничего не выводит.
Больше того, если в коде присутствует указанный вами кусок, Seral.println вообще ничего не выводит(даже произвольный текст), даже если функция main не вызывается...
Возможно проблеммы с конкатенцией символов. Попробуйте убрать все стоковые константы.
{ for (int i=0; i<3; ++i ) { Data &arr = array[i]; Serial.println(i); Serial.println(arr.value1_1); Serial.println(arr.value1_2); Serial.println(arr.value1_3); }; }Просто я теоретик, контроллера у меня пока нет и в натуре проверить код немогу.
Решил проблему. Все дело оказалось по всей видимоcти в имени функции int main() , изменил её на void main1() все заработало.
Но смысла относительно задачи я что-то не увидел. Мы создаем несколько экземпляров структуры в массиве (3 шт), дальше определяем значения для каждого элемента экземпляра структуры.
Но чтобы вызвать эти значения, по прежнему нужно обращаться к элементу по имени, т.е. arr.value
А в данном случае нужен лишь 1 экземпляр структуры, и задача перебрать все элементы, подобно тому, как это делает foreach в php. Потому что ладно если их 5 штук, а если 45?
С другой стороны заменить структуру массивом мы не можем, потому что нужно использовать разные типы данных.
Кажется нащупал решение.. Спасибо за наводку - попробовал подумать над этим с другой стороны, в итоге пришел к тому, что мне нужен Массив массивов структур.
Получилоть вот так (компилится и вроде выводит данные), но хотелось бы убедиться что верно, потому что в ссылках и указателях ниче не понимаю..
struct Data //структура параметров датчиков { float value; double time; int interval; }; Data tempAir[1] = //экземпляр структуры для каждого датчика { // Здесь инициализируются данные, если нужно {1.233,222222,33}, }; Data &tempair=tempAir[0]; //делаем так, чтобы к массиву можно было обращаться как к структуре Data humAir[1]= { // Здесь инициализируются данные, если нужно {69.22,333333,44}, }; Data &humair=humAir[0]; Data *Array[2]={tempAir, humAir}; //объединяем все датчики в 1 массив void setup() { Serial.begin(9600); main1(); //вызов функции перебора float q; //пробуем присвоить начение переменной q=tempair.value; Serial.println(q); int in=1020; //пробуем изменить значение структуры humair.interval=in; Serial.println(humair.interval); } void loop() { } void main1() { for (int i=0; i<2; ++i ) { Data &arr = *Array[i]; //перебо всех значений всех датчиков Serial.println(i); Serial.println(arr.value); Serial.println(arr.time); Serial.println(arr.interval); }; }Выводит:
0
1.23
222222.00
33
1
69.22
333333.00
44
1.23
1020
Вы по сути повторили мой код, только усложнили его.
По сути да, так и есть. просто в начале из ваших примеров я понял что в структуре планируется использовать перечень датчиков (как в моем первом примере), а потом посмотрел иначе, что в структуре нужно размещать параметры датчиков - тогда все обретает смысл.
Но код пришлось усложнить, чтобы иметь возможность обращаться в коде к каждому датчику отдельно. Я немного увлекся и написал лишнего, можно было бы обойтись вот такой конструкцией:
struct Data { float value; double time; int interval; }; Data Array[2]= { // Здесь инициализируются данные, если нужно {1.233,222222,33}, {69.22,333333,44}, }; Data &tempAir=Array[0]; Data &humAir=Array[1];Результат тот же.
Единственное - для меня пока остаются непонятными механизмы того как это работает.. я имею ввиду операторы & и * . поэтому использую их почти наугад.
на почту вам написал, мэйлагентом не пользуюсь.
Ну теперь другое дело, посмотрите в скайп.
Подниму тему.
Есть структура в файле srCh.h, и в основном скетче необходимо перебрать все каналы и прописать каждому каналу значения maxV и minV снятые с соответсвующих аналоговых входов
Для этого перебираю массив и передаю структуру в функцию readState
for ( int i=0; i < chCount; i++ ) chArray[i].state = readState( chArray[i] );Но значения сохраняются в пределах функции readState и глубже
Не сохраняясь в основном массиве каналов "chArray"
Вопрос - как записать данные в основной массив при такой структуре функций?
-----------------------------
Вот подробный код srCh.h
// Структура кодов typedef struct { const char* cName; // Имя канала, не используется в коде int enable; // отключение канала при обнаружении ошибки const int pIn; // Порт чтения статуса устройства const int pOut; // Порт управления устройством int state; // Результаты измерений pIn int maxV; // Максимальное измеренное значение диапазона int minV; // Минимальное измеренное значение диапазона } srCh; srCh chArray[2] = //экземпляр структуры для каждого датчика { // Здесь инициализируются данные, если нужно {"ch1", 1, A0, 2, 0, 0, 1023}, {"ch2", 1, A1, 3, 0, 0, 1023}, }; srCh &ch1=chArray[0]; //делаем так, чтобы к массиву можно было обращаться как к структуре srCh &ch2=chArray[1]; //делаем так, чтобы к массиву можно было обращаться как к структуреВот подробный код скетча
void setup() { // подсчет количества прописанных каналов chCount = sizeof(chArray)/sizeof(*chArray); for ( int i=0; i < chCount; i++ ) { // перебор всех каналов и установка портов вывода pinMode (chArray[i].pOut, OUTPUT); } for ( int i=0; i < chCount; i++ ) { // self test всех каналов if ( chArray[i].enable == 1 ) {// чтение состояния канала, если он не отключен в srCh.h chArray[i].enable = selfTest( chArray[i] ); } } } int selfTest( srCh ch ) { // self test канала // прогон канала до крайнего значения digitalWrite ( ch.pOut, HIGH) ; delay ( fT ); // задержка с запасом на прогон всего канала digitalWrite ( ch.pOut, LOW) ; delay(200); // замер первого значения int s1 = readState ( ch ); digitalWrite ( ch.pOut, HIGH) ; delay ( fT ); digitalWrite ( ch.pOut, LOW) ; delay(200); // замер второго значения int s2 = readState ( ch ); // вычисление диапазона измерений int d = s1 - s2 ; d = abs(d); if ( d >= mR) // mR значение рабочего диапазона { // если измеренный диапазон равен или больше рабочих значений // запишем значения ch.maxV = max(s1, s2); ch.minV = min(s1, s2); return 1; // вернуть TRUE } return 0; // при ошибке вернуть FALSE } int readState( srCh ch ) { // Чтение состояния канала int sens = analogRead(ch.pIn); // прочитать значение на входе sens = map(sens, 0, 1023, 1023, 0); // перевернуть значение // вычислим разницу между измерениями int diff = ch.state - sens ; diff = abs(diff); if ( diff > thrsh ) // thrsh - диапазон погрешности { ch.state = sens; } return ch.state; }В функции selftest и readstate передаются копии структур, а не указатели, поэтому все, что заносится внутри функций идёт лесом.
Собственно вопрос - передавать указатель положения в массиве
или есть другой способ?
Передавать указатель на структуру
а можно в виде примера ?
http://bfy.tw/38Bs