Vectors in Arduino
Vectors in Arduino
我正在Arduino上创建一个"路点"向量。每个航路点都是一个对象。Arduino显然需要为航路点导航存储多个航路点。但是,用户需要能够添加、删除路点并四处移动,而不是将这些路点存储在标准的预编程阵列中。不幸的是,Arduino没有提供向量类型作为内置库。
我目前正在考虑两种选择:
-
在像C++这样的对象的容器中"vector",有人发布了一个通用库。它不包含任何索引删除或移动操作。但它确实包含了一些内存管理策略。
-
我过去使用过malloc、dealloc、calloc。但我一点也不喜欢这种选择,尤其是在上课的时候。但这对我来说是一个更好的选择吗?
哪一条路走得更好?
Arduino的标准C++可能是一个选项。它允许您在Arduino中使用STL矢量。
您可以编写这个LinkedList模板类,只需在任意位置调用它:
#ifndef LinkedList_hpp
#define LinkedList_hpp
template <class T>
class ListNode {
public:
T element;
ListNode* next;
ListNode* prev;
ListNode(T element, ListNode* prev, ListNode* next) : element(element)
{
this->next = next;
this->prev = prev;
};
};
template <class T>
class LinkedList {
private:
int length;
ListNode<T>* head;
ListNode<T>* tail;
ListNode<T>* curr;
public:
LinkedList();
LinkedList(const LinkedList<T>&);
~LinkedList();
T& getCurrent();
T& First() const;
T& Last() const;
int getLength();
void Append(T);
void DeleteLast();
void DeleteFirst();
void DeleteCurrent();
bool next();
bool moveToStart();
bool prev();
void Delete(T&);
bool Search(T);
void Clear();
void PutFirstToLast();
void Update(T elem);
LinkedList& operator = (const LinkedList<T>&);
};
template <class T>
LinkedList<T>::LinkedList() {
length = 0;
head = nullptr;
tail = nullptr;
curr = nullptr;
}
template <class T>
LinkedList<T>::LinkedList(const LinkedList<T> & list) {
length = 0;
head = nullptr;
tail = nullptr;
curr = nullptr;
ListNode<T> * temp = list.head;
while(temp != nullptr)
{
Append(temp->element);
temp = temp->next;
}
}
template <class T>
LinkedList<T> & LinkedList<T>::operator=(const LinkedList<T> & list)
{
Clear();
ListNode<T> * temp = list.head;
while(temp != nullptr)
{
Append(temp->element);
temp = temp->next;
}
return *this;
}
template <class T>
LinkedList<T>::~LinkedList() {
Clear();
}
template<class T>
T& LinkedList<T>::getCurrent()
{
return curr->element;
}
template<class T>
T& LinkedList<T>::First() const
{
return head->element;
}
template<class T>
T& LinkedList<T>::Last() const
{
return tail->element;
}
template<class T>
int LinkedList<T>::getLength()
{
return length;
}
template <class T>
void LinkedList<T>::Append(T element)
{
ListNode<T> * node = new ListNode<T>(element, tail, nullptr);
if(length == 0)
curr = tail = head = node;
else {
tail->next = node;
tail = node;
}
length++;
}
template <class T>
void LinkedList<T>::DeleteLast()
{
if(length == 0)
return;
curr = tail;
DeleteCurrent();
}
template <class T>
void LinkedList<T>::DeleteFirst()
{
if(length == 0)
return;
curr = head;
DeleteCurrent();
}
template <class T>
bool LinkedList<T>::next()
{
if(length == 0)
return false;
if(curr->next == nullptr)
return false;
curr = curr->next;
return true;
}
template <class T>
bool LinkedList<T>::moveToStart()
{
curr = head;
return length != 0;
}
template<class T>
bool LinkedList<T>::prev()
{
if(length == 0)
return false;
if(curr->prev != nullptr)
return false;
curr = curr->prev;
return true;
}
template <class T>
void LinkedList<T>::Delete(T & elem)
{
if(Search(elem))
DeleteCurrent();
}
template <class T>
void LinkedList<T>::DeleteCurrent()
{
if(length == 0)
return;
length--;
ListNode<T> * temp = curr;
if(temp->prev != nullptr)
temp->prev->next = temp->next;
if(temp->next != nullptr)
temp->next->prev = temp->prev;
if(length == 0)
head = curr = tail = nullptr;
else if(curr == head)
curr = head = head->next;
else if(curr == tail)
curr = tail = tail->prev;
else
curr = curr->prev;
delete temp;
}
template <class T>
bool LinkedList<T>::Search(T elem)
{
if(length == 0)
return false;
if(moveToStart())
do {
if(curr->element == elem)
return true;
} while (next());
return false;
}
template <class T>
void LinkedList<T>::PutFirstToLast()
{
if(length < 2)
return;
ListNode<T>* temp = head->next;
head->next->prev = nullptr;
head->next = nullptr;
head->prev = tail;
tail->next = head;
tail = head;
head = temp;
}
template <class T>
void LinkedList<T>::Update(T elem)
{
if(Search(elem))
curr->element = elem;
}
template <class T>
void LinkedList<T>::Clear()
{
if(length == 0)
return;
ListNode<T> * temp = head;
while(temp != nullptr)
{
head = head->next;
delete temp;
temp = head;
}
head = curr = tail = nullptr;
length = 0;
}
#endif
按如下方式使用此类:
LinkedList<int> list;
list.Append(1);
list.Append(2);
list.Append(3);
list.Append(4);
int my_integer;
if(list.moveToStart())
do{
my_integer = list.getCurrent();
}while(list.next());
听起来您想要实现一个简单的链表。链表允许您在没有C++向量相关开销的情况下四处移动对象(在您的情况下是路点)。
以下是GitHub 上的一个实现
arduino的内存有限,因此您需要知道您将允许多少路点。在这种情况下,一个保存已分配路点的内存指针(地址)的简单数组将提供您需要的序列/顺序。保留一个空闲的阵列插槽作为工作区域将允许路点四处移动(重新排序)。
您也可以有一个固定的航路点结构阵列,如果该航路点是否在使用,则在结构中包含一个变量。当添加一个航路点时,你必须在数组中循环,直到找到一个未使用的结构。
如果您想创建一个int向量,arduino有以下内存规范。在Arduino Uno(和其他基于ATmega的板)中,int存储16位(2字节)的值。这保证了范围为-32.768到32.767(最小值为-2^15,最大值为(2^15)-1)。在Arduino Due和其他基于SAMD计算机的板(如MKR1000和Zero)中,int存储32位值(4字节)。这保证了-2147483648到2147483647的范围(最小值-2^31,最大值(2^31)-1)。请参阅此处的更多信息
我不会在任何安全关键设备上的Arduino运行时使用std::vector<>
或任何其他类型在后台进行动态内存分配。它为Arduino打开了由于堆栈溢出而导致严重、不安全崩溃的可能性。
相反,运行时安全需要的是一个固定大小的内存池,它是静态分配的,或者在程序初始化时动态分配一次,但在运行时永远不会增加您的"矢量";应该是一个自定义向量类、数组、链表或库,它在运行时使用这个固定大小的内存池
用户需要能够添加、删除航路点并在周围移动它们
在我看来,最简单的方法是使用静态分配的结构数组作为内存池。静态数组中的每个结构都将是一个链表节点
您在数组中有一个固定的这些节点的最大数量,以防止堆栈溢出。添加,";删除";,并且重新安排路点的顺序现在是完全可能的。添加和";删除";将简单地从链表中删除节点,然后通过更改指向的节点以及顺序来进行重新排列。
现在,对于像Arduino这样的安全关键、内存受限的微控制器来说,这可以以完全安全的方式完成。同样,结构的静态数组是您的";存储器池";,您将使用一个手动实现的节点链表,所有这些节点都位于结构的静态数组中。
- 在执行其他功能的同时播放动画(LED矩阵和Arduino/ESP8266)
- netcat command in c++
- Difference in displaying cv2 Mat
- Arduino:for/while/if在void setup()或void loop()之前?——错误:之前需要不合格
- C++ MFC Libraries in Travis CI
- 如何在OpenSSL中从configuration.h.in获取configuration.h
- 人脸跟踪arduino代码的优化
- vscode下的Arduino代码出现意外编译错误
- Arduino从Txt读取整数
- 创建具有 new in 函数和"this is nullptr"异常的对象
- IN, OUT, INOUT Parameters
- Arduino C++在构造函数中用参数声明对象数组
- 应用程序崩溃并显示"symbol _ZdlPvm, version Qt_5 not defined in file libQt5Core.so.5 with link time reference"
- 有人安装"IITB Simplecpp in mac"吗?
- Serial.print in arduino 不写变量
- 我正在开发Arduino Uno。错误:开关外壳的"'RX' not declared in the scope."和"duplicate case value"
- Vectors in Arduino
- Libraries in Arduino IDE 1.0
- File.getFilename() in Arduino?
- Arduino 错误"unable to find a register to spill in class 'NO_REGS'"