#1 2022-01-31 10:44:54

VLDnepr
Учасник
З г.Днепр
Зареєстрований: 2020-02-04
Повідомлень: 19

Помогите с динамическим массивом

Добрый день. Помогите начинающему.
Хочу сделать управление поливом. Плата UNO.

Создал структуру CONFIG для хранения конфирационных данных.
- poliv_ZoneCount - количество зон
- poliv_ZonePin - динамический массив номеров зон (по количеству зон)
- poliv_Plans - динамический массив структур плана полива PolivPlan_t, структура собержит время старта и динамический массив таймингов полива зон (по количеству зон)

В void setup() сначала задаю количество зон и количество планов, переконфигурируется переменная CONFIG и потом заполняется.
Для теста сразу выводится конфигурация.

Проблема:
1.Помогите пожалуйста оценить правильно ли я работаю с массивами
2.Иногда код выводит неожиданные числа в тайминге плана, при чем именно в тайминге, стартовое время показывается правильно


Пример правильного вывода
poliv_Plan:0 active:1 time:12:33 timers:5 6 7 8 9 10 11

Но иногдла показывает
poliv_Plan:0 active:1 time:12:33 timers:21 32 8 56 0 1 0


#include <EEPROM.h>

#define SerialSpeed 9600
#define InvBit(reg, bit)    reg ^= (1<<(bit))

bool needRestart = false;

// Структура объекта ЗонаПолива
typedef struct PolivPlan_t{
  bool Active ;
  uint8_t TimeStartH; 
  uint8_t TimeStartM;
  uint8_t *poliv_ZoneTimes=0; // массив Таймингов для каждой зоны
  } ;

struct configObj {
  bool serialShow; // показывать диагностический вывод
  bool poliv_Active; // полив может запускаться
  uint8_t poliv_ZoneCount; // количество зон полива
  uint8_t poliv_PlanCount; // количество планов полива
  uint8_t *poliv_ZonePin=0; // Массив номеров зон полива
  PolivPlan_t *poliv_Plans=0;// Массив зон полива
  byte controlByte = 0x55;
} config;


//-----------------------------------------------------------------------
void printConfig();



void ConfigSave(){
  uint16_t startingAddress = 0;
  EEPROM.put(startingAddress, config); startingAddress += sizeof(config); 
  //poliv zone pins
  for (uint8_t _zone=0; _zone<config.poliv_ZoneCount; _zone++){
    EEPROM.put(startingAddress, config.poliv_ZonePin[_zone]); startingAddress += sizeof(config.poliv_ZonePin[_zone]);
  }
  //poliv plans
  for (uint8_t _plan=0; _plan<config.poliv_PlanCount; _plan++) {
    EEPROM.put(startingAddress, config.poliv_Plans[_plan].Active); startingAddress += sizeof(config.poliv_Plans[_plan].Active);
    EEPROM.put(startingAddress, config.poliv_Plans[_plan].TimeStartH); startingAddress += sizeof(config.poliv_Plans[_plan].TimeStartH);
    EEPROM.put(startingAddress, config.poliv_Plans[_plan].TimeStartM); startingAddress += sizeof(config.poliv_Plans[_plan].TimeStartM);
    for (uint8_t _zone=0; _zone<config.poliv_ZoneCount; _zone++) {
      EEPROM.put(startingAddress, config.poliv_Plans[_plan].poliv_ZoneTimes[_zone]); startingAddress += sizeof(config.poliv_Plans[_plan].poliv_ZoneTimes[_zone]);
    }
  }
}


void ConfigLoad(){
Serial.print("np1");  
  uint16_t startingAddress = 0;
  EEPROM.get(startingAddress, config); startingAddress += sizeof(config); 
  config.poliv_ZonePin=0;
  config.poliv_Plans=0;

  ChangeConfig();
  
  //poliv zone pins
  for (uint8_t _zone=0; _zone<config.poliv_ZoneCount; _zone++){
    EEPROM.get(startingAddress, config.poliv_ZonePin[_zone]); startingAddress += sizeof(config.poliv_ZonePin[_zone]);
  }
  //poliv plans
  for (uint8_t _plan=0; _plan<config.poliv_PlanCount; _plan++) {
    EEPROM.get(startingAddress, config.poliv_Plans[_plan].Active); startingAddress += sizeof(config.poliv_Plans[_plan].Active);
    EEPROM.get(startingAddress, config.poliv_Plans[_plan].TimeStartH); startingAddress += sizeof(config.poliv_Plans[_plan].TimeStartH);
    EEPROM.get(startingAddress, config.poliv_Plans[_plan].TimeStartM); startingAddress += sizeof(config.poliv_Plans[_plan].TimeStartM);
    for (uint8_t _zone=0; _zone<config.poliv_ZoneCount; _zone++) {
      EEPROM.get(startingAddress, config.poliv_Plans[_plan].poliv_ZoneTimes[_zone]); startingAddress += sizeof(config.poliv_Plans[_plan].poliv_ZoneTimes[_zone]);
    }
  }
}

void ChangeConfig(){
  //--- poliv_ZonePin
  config.poliv_ZonePin = (uint8_t*) realloc(config.poliv_ZonePin, config.poliv_ZoneCount * sizeof(uint8_t));

  //--- poliv_Plans
  config.poliv_Plans = (PolivPlan_t*) realloc(config.poliv_Plans, config.poliv_PlanCount * sizeof(PolivPlan_t));
  for (uint8_t _plan=0; _plan<config.poliv_PlanCount; _plan++) {
    config.poliv_Plans[_plan].poliv_ZoneTimes = (uint8_t*)realloc(config.poliv_Plans[_plan].poliv_ZoneTimes, config.poliv_ZoneCount * sizeof(uint8_t));
  }
}

void setup() {//=== SETUP ======= SETUP ======= SETUP 
  Serial.begin(SerialSpeed);


  // --- Предварительная запись в EEPROM ----
  Serial.println(F("test varialbe set"));
  config.poliv_Active = true;
  config.poliv_ZoneCount = 7;
  config.poliv_PlanCount = 1;
  config.poliv_ZonePin = 0; // первоначальная инициализация перед заполнением из EEPROM
  config.poliv_Plans = 0;   // первоначальная инициализация перед заполнением из EEPROM

  Serial.println(F("nChangeConfig();"));
  ChangeConfig(); // переконфигурирование CONFIG

  Serial.println(F("test varialbe set next"));
  config.poliv_ZonePin[0] = 20;
  config.poliv_ZonePin[1] = 21;
  config.poliv_ZonePin[2] = 22;
  config.poliv_ZonePin[3] = 23;
  config.poliv_ZonePin[4] = 24;
  config.poliv_ZonePin[5] = 25;
  config.poliv_ZonePin[6] = 26;
  config.poliv_Plans[0].Active = true;
  config.poliv_Plans[0].TimeStartH = 12;
  config.poliv_Plans[0].TimeStartM = 33;
  config.poliv_Plans[0].poliv_ZoneTimes[0] = 5;
  config.poliv_Plans[0].poliv_ZoneTimes[1] = 6;
  config.poliv_Plans[0].poliv_ZoneTimes[2] = 7;
  config.poliv_Plans[0].poliv_ZoneTimes[3] = 8;
  config.poliv_Plans[0].poliv_ZoneTimes[4] = 9;
  config.poliv_Plans[0].poliv_ZoneTimes[5] = 10;
  config.poliv_Plans[0].poliv_ZoneTimes[6] = 11;

  printConfig();

  Serial.println(F("nChangeSave()"));
  ConfigSave();


/*  Serial.println(F("nConfigLoad()"));
  ConfigLoad();
  Serial.println("nAFTER LOAD");

  printConfig();
*/  
}

  
void loop(){
/*  Serial.println("nvoid loop()");
  printConfig();
  delay(1000);
*/  
}


void printConfig() {//--- Вывод текущей конфигурации ----------
  Serial.print(F("Current config")); 
  if (needRestart) Serial.print(F(" !!! Need restart !!!"));
  Serial.println(); 
  Serial.print(F("serial show:")); Serial.println(config.serialShow);
  Serial.print(F("poliv_Active:")); Serial.println(config.poliv_Active);
  Serial.print(F("poliv_ZoneCount:")); Serial.print(config.poliv_ZoneCount); 
    Serial.print(F(" contact numbers:"));  for (uint8_t _zone=0; _zone<config.poliv_ZoneCount; _zone++){Serial.print(config.poliv_ZonePin[_zone], DEC); Serial.print(" ");} Serial.println();
  Serial.print(F("poliv_PlanCount:")); Serial.println(config.poliv_PlanCount);

  // poliv plan
  for (uint8_t _plan=0; _plan<config.poliv_PlanCount; _plan++) {
    Serial.print(F("poliv_Plan:")); Serial.print(_plan);
    Serial.print(F(" active:")); Serial.print(config.poliv_Plans[_plan].Active);
    Serial.print(F(" time:")); Serial.print(config.poliv_Plans[_plan].TimeStartH);Serial.print(F(":")); Serial.print(config.poliv_Plans[_plan].TimeStartM);
    Serial.print(F(" timers:"));
    for (uint8_t _zone=0; _zone<config.poliv_ZoneCount; _zone++) {
      Serial.print(config.poliv_Plans[_plan].poliv_ZoneTimes[_zone]);Serial.print(F(" "));
    }
    Serial.println();
  }
}

Остання редакція VLDnepr (2022-01-31 10:45:40)

Неактивний

#2 2022-01-31 21:14:19

renoshnik
Учасник
Зареєстрований: 2017-04-03
Повідомлень: 1,025

Re: Помогите с динамическим массивом

это что-то такое ?

https://www.drive2.ru/b/1025112/

https://www.drive2.ru/c/1033572/

Неактивний

#3 2022-02-01 09:47:41

Honey
Учасник
З Київ
Зареєстрований: 2020-09-26
Повідомлень: 433

Re: Помогите с динамическим массивом

Когда Вы делаете realloc(config.poliv_Plans[_plan].poliv_ZoneTimes, ...); то последние значения config.poliv_Plans[_plan].poliv_ZoneTimes (до индекса config.poliv_PlanCount и начиная с его предыдущего значения) находятся в только что выделенной (расширенной) области памяти и не инициализированы. Чтобы инициализировать нулями только нужные (новые), Вам нужна информация о предыдущем значении config.poliv_PlanCount.

Неактивний

#4 2022-02-01 12:30:12

VLDnepr
Учасник
З г.Днепр
Зареєстрований: 2020-02-04
Повідомлень: 19

Re: Помогите с динамическим массивом

Honey пише:

Когда Вы делаете realloc(config.poliv_Plans[_plan].poliv_ZoneTimes, ...); то последние значения config.poliv_Plans[_plan].poliv_ZoneTimes (до индекса config.poliv_PlanCount и начиная с его предыдущего значения) находятся в только что выделенной (расширенной) области памяти и не инициализированы. Чтобы инициализировать нулями только нужные (новые), Вам нужна информация о предыдущем значении config.poliv_PlanCount.

Это как раз понятно и будет отработано.

Осенила другая мысль

void ConfigLoad(){
Serial.print("np1");  
  uint16_t startingAddress = 0;
  EEPROM.get(startingAddress, config); startingAddress += sizeof(config); 
  config.poliv_ZonePin=0;
  config.poliv_Plans=0;

  ChangeConfig();

Строки   
  config.poliv_ZonePin=0;
  config.poliv_Plans=0;

Переменные являются указателями на динамические массивы. Предполагалось что строки сбросят указатели, т.е. они не должны указывать никуда.
Но помоему в этом написании я не сбрасываю указатель, а изменяю значение, на которое указывает указатель?
Как правильно сбросить указатель, чтобы сам указатель был NULL?

Неактивний

#5 2022-02-01 21:25:12

Honey
Учасник
З Київ
Зареєстрований: 2020-09-26
Повідомлень: 433

Re: Помогите с динамическим массивом

NULL это (void*)0, можно писать config.poliv_Plans=0, а можно config.poliv_Plans=NULL, просто в первом случае будет предупреждение компилятора о несоответствии типов. Пишите всегда NULL, если присваиваете указателю, считайте это правилом хорошего тона.

Неактивний

#6 2022-02-07 18:06:10

shyam
Гість

Re: Помогите с динамическим массивом

Массивы индексируются, начиная с 0. Если вы введете 1 вместо x, ваш массив будет иметь длину 1, и этот один элемент будет проиндексирован как числа[0]. number[1] не существует, отсюда и ошибка.

Швидке повідомлення

Введіть повідомлення і натисніть Надіслати

Підвал форуму