Как удалить структурные записи в C - PullRequest
0 голосов
/ 03 декабря 2009

Из списка структур, как мы можем удалить несколько из них. После удаления структуры не должно быть свободного места.

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

   struct symtab *sp;
   for(sp = symtab; sp < &symtab[NSYMS]; sp++)
       if(sp->scope == scope) // delete
       {
           sp = sp+1;

       }

Ответы [ 5 ]

2 голосов
/ 03 декабря 2009

Вы можете использовать memmove ():

//pseudocode, not tested
struct symtab* end = &symtab[NSYMS];
for(sp = symtab; sp < end; sp++) {
    if(sp->scope == scope) {
        memmove( sp, sp + 1, (end - sp) * sizeof(struct symtab);
        sp++;
        end--;
    }
}            

обратите внимание, что end можно изменить, так как массив может стать "короче". Другой код, который работает с этим массивом, должен иметь доступ только к сокращенной области.

1 голос
/ 03 декабря 2009

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


struct symtab *sp;
struct symtab *endp; // end of array pointer

endp = symtab + NSYMS; 
for ( sp = symtab + NSYMS - 1; sp >= symtab; sp-- ) {
    if ( sp->scope = scope ) {
        int numelems = endp - (sp + 1);
        if ( numelems > 0 ) {
            memmove( sp, sp + 1, numelems );
            endp--; // adjust end of array pointer
        }
    }
}
1 голос
/ 03 декабря 2009

Вы не можете сделать это с массивами в стиле C (*). Лучше всего реализовать его в виде связанного списка, который может быть любым из одинарных или двойных ссылок.

(*) Если вы должны использовать массивы, вы можете сделать memmove от следующего элемента до элемента, который вы хотите удалить. Однако в этом случае вы также должны обновить значение NSYMS, которое, как может показаться, является #define, невозможно.

0 голосов
/ 03 декабря 2009

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

0 голосов
/ 03 декабря 2009

Есть несколько вариантов:

  • Продолжайте использовать массив фиксированного размера, но используйте значение часового поля (например, -1) для ключевого поля, чтобы вы знали, какие записи не используются. Когда вам нужно добавить запись, найдите следующий неиспользуемый слот. Это все еще страдает от ограничения наличия массива фиксированного размера.

  • Используйте memmove, как указано в других ответах. Это не очень эффективно.

  • Используйте связанный список вместо фиксированного массива, тогда вы можете легко (и дешево) удалить записи, а также добавить.

По сути, если вы не пишете код для какой-либо встроенной системы, имеющей жесткие ограничения памяти, вероятно, нет веской причины устанавливать произвольный верхний предел массива. Другие структуры (такие как связанный список) могут быть легко добавлены или удалены, и есть множество библиотек, которые предоставляют такие контейнеры.

И после всего этого вы уверены, что вам не нужна хеш-таблица (или словарь), если вы управляете таблицей символов?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...