Comment supprimer des entrées de structure en C

Dans une liste de structures, comment pouvons-nous en supprimer quelques-unes? Après avoir supprimé la structure, il ne doit plus restr aucun espace vide.

Le code suivant a été essayé pour accomplir la tâche, mais cela n’a pas fonctionné.

struct symtab *sp; for(sp = symtab; sp scope == scope) // delete { sp = sp+1; } 

Vous pouvez utiliser 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--; } } 

notez que end peut être modifié car le tableau pourrait devenir “plus court”. Les autres codes fonctionnant avec ce tableau doivent uniquement accéder à la région raccourcie.

Vous ne pouvez pas faire cela avec des tableaux de style C (*). Le mieux est de l’implémenter sous forme de liste chaînée, qu’il s’agisse de liens simples ou doubles.

(*) Si vous devez utiliser des tableaux, vous pouvez faire un déplacement de l’élément suivant vers l’élément que vous souhaitez supprimer. Cependant, vous devez également mettre à jour la valeur de NSYMS dans ce cas, ce qui, il semblerait qu’il s’agisse d’une #define, impossible.

Vous pouvez revenir en arrière dans le tableau. En avant ou en arrière, toutefois, la suppression d’un élément au début de la liste en terme de quantité de mémoire devant être déplacée entraîne une pénalité croissante. Pour cette raison, supprimer d’abord les entrées à la fin du tableau pourrait légèrement améliorer les performances.

 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 } } } 

Il y a quelques options:

  • Continuez à utiliser un tableau de taille fixe, mais utilisez une valeur sentinel (par exemple, -1) pour le champ clé, afin de savoir quelles entrées sont inutilisées. Lorsque vous devez append une entrée, recherchez le prochain emplacement inutilisé. Cela souffre toujours de la limitation d’avoir un tableau de taille fixe.

  • Utilisez memmove comme indiqué dans d’autres réponses. Ce n’est pas très efficace.

  • Utilisez une liste chaînée au lieu d’un tableau fixe, vous pourrez ainsi supprimer (et à moindre coût) des entrées, ainsi qu’append.

Fondamentalement, à moins d’écrire du code pour un système intégré soumis à de sévères contraintes de mémoire, il n’y a probablement aucune bonne raison de placer une limite supérieure arbitraire sur le tableau. D’autres structures (telles qu’une liste chaînée) peuvent facilement être ajoutées ou supprimées. De nombreuses bibliothèques fournissent de tels conteneurs.

Et après tout cela, êtes-vous sûr de ne pas vouloir une table de hachage (ou un dictionnaire) si vous gérez une table de symboles?

La meilleure solution consiste à utiliser une liste chaînée contenant les structures. Comme mentionné ci-dessus, cela est très inefficace avec les tableaux, car vous devez déplacer les données si elles ne sont pas supprimées à la fin.