Массив строк - как определить количество присутствующих элементов

Я хотел бы использовать массив строк, который я определяю следующим образом:

char* CommandQueue[]={"FirstCommend", "SecondCommend", "ThirdCommand", "Cmd4", "Cmd5"};

Цель этого массива — хранить команды («строки различной длины»), которые Arduino будет получать через последовательный порт. Эти команды будут интерпретироваться путем вызова соответствующих функций обратного вызова для их обработки. CommandQueue должен выстраивать команды в своего рода «буфер».

Изначально массив "CommandQueue" не содержит никаких элементов и заполняется во время выполнения проекта. Массив будет постоянно опрашиваться, и как только команда будет интерпретирована (и соответствующая функция будет выполнена), команда будет исключена из очереди.

Как определить, сколько элементов (т. е. строк) или команд присутствует в массиве? Функция sizeof() не поможет, поскольку отдельные элементы могут иметь разную длину.

Заранее спасибо за вашу помощь или комментарии.

, 👍-1

Обсуждение

Просто используйте переменную для его хранения... Я думаю, это правильный способ обработки буфера..., @frarugi87


4 ответа


1

Вам нужно знать, какова длина очереди команд, или просто есть ли в ней еще элементы? Это похоже на случай, когда вам лучше использовать другую структуру данных — связанный список кажется очевидной возможностью. Если вы не знакомы со связанными списками, эта статья может быть полезна. В противном случае, я думаю, вам нужно будет отслеживать количество элементов в очереди самостоятельно.

Если вы используете массив, его необходимо объявить с фиксированной длиной, например:

 char * CommandQueue[MAX_QUEUE_LENGTH];

Оператор sizeof сообщит вам длину массива, но не количество элементов в нем (длина массива — это количество указателей символов, определенное MAX_QUEUE_LENGTH). Код для управления очередью команд как массивом может стать довольно запутанным, особенно если вам нужно выполнить команды по порядку.

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

,

2

Вы не можете узнать, сколько элементов находится в массиве, просто потому, что массив имеет фиксированный размер, и не существует такого понятия, как «не запись».

Самое близкое, что вы можете иметь, — это массив фиксированного размера, и только некоторые записи в нем являются допустимыми — те, которые недопустимы, имеют специальное значение, которое говорит «это недопустимая запись». Для указателей char обычно используют NULL как значение «недопустимая запись».

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

В этой ситуации лучше использовать кольцевой буфер, который является массивом фиксированного размера, но вы удаляете концепцию "первой" записи. Вместо этого у вас есть "головное" и "хвостовое" значения, которые являются позициями в массиве, откуда вы читаете (удаляете самые старые) и куда записываете (добавляете после самых новых). Так последовательный порт на Arduino обрабатывает входящие и исходящие данные — по мере поступления данных они добавляются в кольцевой буфер, а затем вы читаете из этого буфера.

Чтобы облегчить работу с циклическими буферами, я написал небольшой шаблон класса:

  • https://github.com/MajenkoLibraries/CircularBuffer
,

1

Очень полезный макрос — membersof().

#define membersof(x) (sizeof(x) / sizeof(x[0]))

Вы найдете в определенных больших библиотеках и фреймворках для C/C++. Для вашего примера выше количество элементов равно:

const int COMMAND_QUEUE_MAX = membersof(CommandQueue);
...
for (int i = 0; i < COMMAND_QUEUE_MAX; i++) ...

Для динамического набора потребуется максимальная длина и нуль-терминатор или просто счетчик.

const int COMMAND_QUEUE_MAX = ...;
char* CommandQueue[COMMAND_QUEUE_MAX] = { ....., NULL };

for (char** cpp = CommandQueue; *cpp != NULL; cpp++) {
  char* name = *cp;
  ...
}

Или еще лучше использовать тип данных Queue:

Queue<char*, COMMAND_QUEUE_MAX> CommandQueue;
...
char* cp;
while (CommandQueue.dequeue(&cp)) ...

Ура!

,

-2

Я знаю, что это старый вопрос, но вот быстрый и грязный способ получить количество элементов в динамическом массиве.

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

int numberOfElements = 0

for(int i=0; yourArray[i].length() != 0; i++){
  numberOfElements++;
} 
,

char* не является классом, поэтому у него не может быть метода .length(). И если бы все элементы имели строки ненулевой длины, ваш код вышел бы за границы., @gre_gor