如何获取未达上限的结构体数组当前已写入记录数?
嘿,这个问题在缓冲区处理场景里挺常见的,我给你几个实用的解决方案,你可以根据你的实际需求来选:
这是最简单高效的方式——既然你是通过缓冲区写入函数依次添加元素,那直接在每次成功写入时更新一个计数变量就行。要获取当前已写入的记录数,直接读这个变量就好,时间复杂度是O(1),完全没额外开销。
示例代码:
// 定义一个和缓冲区同生命周期的计数变量(可以是全局、静态或者封装在结构体里) uint8_t commandBufferCount = 0; // 假设你的写入函数大概是这样实现的 bool addToCommandBuffer(remoteInstructionReceived_t newCmd) { // 检查是否达到缓冲区上限 if (commandBufferCount < 50) { commandBuffer[commandBufferCount] = newCmd; commandBufferCount++; return true; // 写入成功 } return false; // 缓冲区已满,写入失败 } // 获取当前已写入的记录数 uint8_t getCurrentRecordCount() { return commandBufferCount; }
如果你的系统内存极端受限,没法额外维护计数变量,可以给结构体(或者元素类型)定义一个无效标记值,用它来区分已写入的有效元素和未使用的空位置。
比如假设remoteInstructionReceived_t是一个枚举类型,其中有一个INVALID_INSTRUCTION的枚举值用来标记空位置:
// 假设remoteInstructionReceived_t的定义示例 typedef enum { INVALID_INSTRUCTION, // 无效标记,代表该位置未写入 CMD_MOVE, CMD_STOP, // 其他指令类型... } remoteInstructionReceived_t; // 初始化缓冲区:把所有位置设为无效标记 void initCommandBuffer() { for (uint8_t i = 0; i < 50; i++) { commandBuffer[i] = INVALID_INSTRUCTION; } } // 获取当前已写入的记录数 uint8_t getCurrentRecordCount() { uint8_t count = 0; // 遍历数组,直到遇到无效标记或者数组末尾 while (count < 50 && commandBuffer[count] != INVALID_INSTRUCTION) { count++; } return count; }
⚠️ 注意:这个方案每次获取计数都要遍历数组,时间复杂度是O(n),虽然50个元素的开销不大,但效率不如方案1。另外必须确保写入的元素都是有效值,不能和无效标记冲突。
如果之后你需要给这个缓冲区添加删除头部元素的功能(做成FIFO队列),可以用头尾指针来管理。即使现在只是依次添加,这个方案也能轻松获取计数:
uint8_t bufferHead = 0; // 下一个要写入的位置索引 uint8_t bufferTail = 0; // 第一个有效元素的位置索引 // 写入函数 bool addToCommandBuffer(remoteInstructionReceived_t newCmd) { if (bufferHead < 50) { commandBuffer[bufferHead] = newCmd; bufferHead++; return true; } return false; } // 获取当前已写入的记录数 uint8_t getCurrentRecordCount() { return bufferHead - bufferTail; }
如果只是单纯依次添加不删除元素,bufferTail会一直是0,此时计数就等于bufferHead,和方案1效果一致;之后如果需要删除元素,只需要移动bufferTail即可,扩展性很强。
小提示:看你给出的代码里定义了instructionData_type结构体,但实际缓冲区是remoteInstructionReceived_t类型的。如果实际缓冲区应该是instructionData_type的话,只需要对应调整代码里的字段就行——比如方案2里检查commandBuffer[count].instruction != INVALID_INSTRUCTION。
内容的提问来源于stack exchange,提问作者P47 R1ck

