Как создать динамический массив ардуино?

morfius
morfius аватар
Offline
Зарегистрирован: 06.01.2017

Доброе время.

В файле на флешке список сотрудников и коды доступа. Как это все грамотно загрузить в массив, если его длинна заранее не известна? Копал копал - не накопал. :/

Panzerfunker
Offline
Зарегистрирован: 28.10.2016

Доброе время если еще актуально пишите решим вопрос недорого golinskiy.konstantin@gmail.com

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

В глобальном пространстве имён - только с помощью "сырых" указателей и malloc.  И ручками, ручками. 

а вот внутри класса - лехко. 

работает такие конструкции

using PString = String *;

class blablabla
{
 private:

     PString *(Lines)[];    // массив строк для TFT экрана.  Для разных экранов и шрифтов - разное. 
                            // в С++ это называется указатель на массив указателей на строки. 

использовать: 

    *Lines = new PString[FLinesCount];
    for (byte i = 0; i < FLinesCount; i++)
    {
        (*Lines)[i] = new String("Твой инициализатор строки");
    }

я тоже по всему гуголю искал - обыскался.  методом проб и ошибок только выяснил, что и как. 

кстати,  в ArduIDE не проверял.  У меня Студия 2015+Visual Micro plugin.  Хотя, наерно, это больше от GCC зависит. 

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Кроме массивов есть другие способы хранения данных, например, списки. Весь вопрос в задаче, что лучше использовать массив или список.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Если внутри функции, так просто объявите массив переменной длины прямо в лоб.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

kisoft пишет:
Кроме массивов есть другие способы хранения данных, например, списки. Весь вопрос в задаче, что лучше использовать массив или список.

:))))))

«все настоящие программисты  знают,  единственной  полезной  структурой данных является массив»

:))))))

morfius
morfius аватар
Offline
Зарегистрирован: 06.01.2017

Вопрос в том, как это правильно сделать. Допустим я могу пробежаться по файлу и посчитать количество сотрудников. Объявить массив из этого количества - вот в чем вопрос.

ЕвгенийП пишет:

Если внутри функции, так просто объявите массив переменной длины прямо в лоб.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

morfius пишет:

Вопрос в том, как это правильно сделать. Допустим я могу пробежаться по файлу и посчитать количество сотрудников. Объявить массив из этого количества - вот в чем вопрос.

ЕвгенийП пишет:

Если внутри функции, так просто объявите массив переменной длины прямо в лоб.

Так я ж пишу "прямо так в лоб".

// Мы уже выяснили количество и оно сидит в переменной colvo. (Вы же это можете)
// Теперь вызываем функцию обработки
obrabotka(colvo);

Функция же obrabotka выглядит так:

void obrabotka(const int N) {
     int massiv [N]; // динамический массив нужного размера
     ..........
}

 

morfius
morfius аватар
Offline
Зарегистрирован: 06.01.2017

Вот это круто, если оно так будет работать. Сейчас буду пробовать.

Я вот кстати объявил вот такой массив прямо в setup после подсчета сотрудников

unsigned long listofusers[colvo];

Что меня удивило - так это то, что компилятор не обругался. Буду пробовать оба варианта.

ЕвгенийП пишет:

morfius пишет:

Вопрос в том, как это правильно сделать. Допустим я могу пробежаться по файлу и посчитать количество сотрудников. Объявить массив из этого количества - вот в чем вопрос.

ЕвгенийП пишет:

Если внутри функции, так просто объявите массив переменной длины прямо в лоб.

Так я ж пишу "прямо так в лоб".

// Мы уже выяснили количество и оно сидит в переменной colvo. (Вы же это можете)
// Теперь вызываем функцию обработки
obrabotka(colvo);

Функция же obrabotka выглядит так:

void obrabotka(const int N) {
     int massiv [N]; // динамический массив нужного размера
     ..........
}

 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Короткая лекция, даже, скорее, просто замечание, о распределении памяти при компиляции и работе программ на Ардуино.

1. Стек - это как обойма у автомата Калашникова, - заполняется снизу, для простоты - от адреса 0.. Новый объект в памяти кладется поверх старого и используется. При ненужности - освобождается память, занимаемая самым верхним объектом.

2. Куча - ровно наоборот - растет вниз, от верхнего свободного адреса. Расет куча вниз, к стеку. ВСЯ сободная память - между ними.

========================

Пользуясь этими знаниями можно решать Вашу проблемму двумя способами:

1. поместить массив в стек. Это происходит всегда, когда переменная (в нашем случае массив) объявляется ВНУТРИ функции, после выхода из функции - память освобождается.

Стандарт С++ никаких ограничений на такой массив не накладывает, объявляйте его, также как и статический, просто указав переменную вместо числа:

int  MyArray[length];

Недостатки - покинуть функцию уже нельзя. Весь остальной код, если ему нужен это массив, должен работать внутри функции.

2. Куча. Зная как работает куча на Ардуино, очень легко ей оперировать.

Отведите память с запасом функцией malloc(), но больше всей, конечно!

После заполнения данными - излишки освободите, вызвав  realloc() с уже вычисленным объемом.

Поскольку, по мере заполнения памяти с SD карты, Вы никак не работаете с кучей, то уменьшение запрошенного объема до актуального отработает корректно.

Я бы пошел этим путем. Удобно, модно, молодежно. И не нужно свой список два раза проходить.

//допустим максимальное количество = 100

struct Emp_Code * empcode= (struct Emp_Code *) malloc(sizeof(scruct Emp_code)*100);

for (int i = 0;есть_еще_записи_на_карте;i++)

    {

    заполнить(empcode[i]);

    }

realloc ((void *)empcode, sizeof(scruct Emp_Code)*i);    

 

dardik
Offline
Зарегистрирован: 09.03.2013

Здравствуйте, попробовал применить код, но не компилируется. В C,C++ не силен. Выдает ошибку: invalid application of 'sizeof' to incomplete type 'fillingPressureArray()::Emp_code'

void fillingPressureArray() // Наполнение массива значениями давления из файлов за текущий и предыдущий день
{
  File dataFile = SD.open("4-4-19.log");
  String stroka = "";
  int k = 0;
  //допустим максимальное количество = 100
  struct Emp_Code * empcode = (struct Emp_Code *) malloc(sizeof(struct Emp_code) * 100);
  if (dataFile) {
    while (dataFile.available()) {
      stroka = dataFile.readStringUntil('\n');
      empcode[k] = stroka;
      k++;
      Serial.println(stroka); //Printing for debugging purpose
    }
    dataFile.close();
    realloc ((void *)empcode, sizeof(scruct Emp_Code)*i);
  }
  else {
    Serial.println("error opening 4-4-19.log");
  }
}

Ругается на строку: struct Emp_Code * empcode = (struct Emp_Code *) malloc(sizeof(struct Emp_code) * 100);

 

 

b707
Offline
Зарегистрирован: 26.05.2017

dardik - а сама структура у вас описана? покажите как

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Скетч неполный, потому сказать ничего невозможно. Никто ведь не знает как именно описана struct Emp_Code

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

тут вообще какая-то чушь написана. указатель локален и никуда не отдается. Ошибка там, скорее всего детская - типа скобки не там, но это и не важно.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

wdrakula пишет:

указатель локален и никуда не отдается. 

так и память не освобождается. Но по этому вопросу никаких запросов от автора не поступало. Он спросил за компиляцию :)

dardik
Offline
Зарегистрирован: 09.03.2013

Я не создавал структуру - не знаю как это делается ((. Мне понравился ваш подход, что не надо 2 раза файл перечитывать. С указателями и структурами не работал((. Суть - считать строки с SD карты, распарсить и записать в массив типа int.

 

 

dardik
Offline
Зарегистрирован: 09.03.2013

В коде, что я написал, я пытался строки в массив записать

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Так, а от нас-то Вы чего ждёте? Если Вы не создавали структуру, но пытаетесь завхватить под неё память ... ну, не получается у Вас, понятно. Учитесь создавать структуры. Литературы навалом, в т.ч. в первой теме раздела "Песочница".

dardik
Offline
Зарегистрирован: 09.03.2013

Я понял, буду изучать.

 

salik
Offline
Зарегистрирован: 12.12.2018

ЕвгенийП пишет:

morfius пишет:

Вопрос в том, как это правильно сделать. Допустим я могу пробежаться по файлу и посчитать количество сотрудников. Объявить массив из этого количества - вот в чем вопрос.

ЕвгенийП пишет:

Если внутри функции, так просто объявите массив переменной длины прямо в лоб.

Так я ж пишу "прямо так в лоб".

// Мы уже выяснили количество и оно сидит в переменной colvo. (Вы же это можете)
// Теперь вызываем функцию обработки
obrabotka(colvo);

Функция же obrabotka выглядит так:

void obrabotka(const int N) {
     int massiv [N]; // динамический массив нужного размера
     ..........
}

 

Евгений, а если static int massiv [N] ( т.е. внутри функции obrabotka() объявляется static int massiv [N]) ? Не могу додумать как этом случае быть, компилятор выдает ошибку "error: storage size of 'massiv' isn't constant".

 

sadman41
Offline
Зарегистрирован: 19.10.2016

При static int massiv[N] число N должно быть известно на этапе компиляции.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

salik, ты лучше скажи чотыхошь, а мы скажем четенада. 

salik
Offline
Зарегистрирован: 12.12.2018

sadman41 пишет:

При static int massiv[N] число N должно быть известно на этапе компиляции.

Спасибо