2009-05-18 7 views

Antwort

21

Sie müssen nur überschreiben, was Sie mit dem nächsten Wert in dem Array sind zu löschen, propagieren diese Änderung, und dann im Auge behalten, wo das neue Ende ist:

int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; 

// delete 3 (index 2) 
for (int i = 2; i < 8; ++i) 
    array[i] = array[i + 1]; // copy next element left 

Jetzt Ihr Array ist {1, 2, 4, 5, 6, 7, 8, 9, 9}. Sie können die zusätzliche 9 nicht löschen, da dies ein Array statischer Größe ist, Sie müssen es nur ignorieren. Dies kann mit std::copy erfolgen:

std::copy(array + 3, // copy everything starting here 
      array + 9, // and ending here, not including it, 
      array + 2) // to this destination 

In C++ 11, Verwendung std::move (der Algorithmus Überlastung, nicht das Dienstprogramm Überlastung) verwenden kann, statt.

Allgemeiner verwenden std::remove Elemente zu entfernen, um einen Wert übereinstimmt, gefunden

// remove *all* 3's, return new ending (remaining elements unspecified) 
auto arrayEnd = std::remove(std::begin(array), std::end(array), 3); 

Noch mehr im Allgemeinen, es std::remove_if ist.

Beachten Sie, dass die Verwendung von std::vector<int> hier möglicherweise besser geeignet ist, da es sich um ein "echtes" dynamisch zugewiesenes Größenanpassungs-Array handelt. (In dem Sinne, dass die Frage nach seinem size() spiegelt entfernte Elemente.)

+0

keine Erwähnung von 'copy (iter, iter, iter)' 'oder' move (iter, iter, iter) ''? –

+0

@MooingDuck: Zurück in '09 'move (iter, iter, iter)' existierte nicht. : P Steve Jessop erwähnt es unten, es wäre (hätte) gestohlen, um es in meine Antwort zu stecken, imo. – GManNickG

+0

@GManNickG: stehlen weg - vor allem für alte Fragen Ich denke, das Ideal ist, dass die angenommene Antwort gut ist. Manchmal ist es ein bisschen frech, eine Antwort zu schreiben, die alle die besten Teile der Antworten des anderen birgt, aber ich bin mir ziemlich sicher, dass es dennoch eine anerkannte Praxis ist, ISTR eine FAQ, die es eigentlich empfiehlt. Alles, was ich nicht benutzen möchte, werde ich nicht bei SO posten :-) –

3

Abhängig von Ihren Anforderungen können Sie für diese Vorgangsarten STL-Listen verwenden. Sie können Ihre Liste durchlaufen, bis Sie das Element finden und das Element löschen. Wenn Sie keine Listen verwenden können, müssen Sie alles selbst verschieben, entweder durch einen STL-Algorithmus oder manuell.

+0

Ich zweite der Vorschlag, std :: list zu verwenden. Wenn Sie ein Element aus der Mitte eines Vektors entfernen müssen, müssen Sie alle folgenden Elemente verschieben, was sehr teuer ist (O (n) im Durchschnitt). Das Entfernen eines Elements aus der Mitte einer Liste beim Überfahren ist jedoch eine einfache O (1) -Operation. – newacct

4

Sie können nicht erreichen, was Sie mit Arrays wollen. Verwenden Sie stattdessen Vektoren und lesen Sie über den std :: remove-Algorithmus nach. Etwas wie:

std::remove(array, array+5, 3) 

funktioniert auf Ihrem Array, aber es wird es nicht verkürzen (warum - weil es unmöglich ist). Mit Vektoren, würde es so weit so etwas wie

v.erase(std::remove(v.begin(), v.end(), 3), v.end()) 
+0

Ich denke, es ist unmöglich, da der Speicher bereits reserviert wurde, so dass der ursprüngliche Speicherblock immer noch Informationen über ein 5-Punkt-Array enthält. – Rodrigo

9

std :: Kopie macht den Job sein als bewegliche Elemente angeht:

#include <algorithm> 

std::copy(array+3, array+5, array+2); 

Beachten Sie, dass die Voraussetzung für eine Kopie ist, dass das Ziel muss nicht im Quellbereich sein. Es ist zulässig, dass sich die Bereiche überschneiden.

Aufgrund der Art und Weise, wie Arrays in C++ arbeiten, "verkürzt" dies das Array nicht. Es verschiebt einfach Elemente in ihm. Es gibt keine Möglichkeit, die Größe eines Arrays zu ändern, aber wenn Sie eine separate Ganzzahl verwenden, um ihre "Größe" zu verfolgen, also die Größe des Teils, der Ihnen wichtig ist, können Sie das natürlich verringern.

Also, das Array, das Sie mit wird am Ende werde sein, als ob es mit initialisiert wurden:

int array[] = {1,2,4,5,5}; 
20

Sie memmove() verwenden können, aber Sie haben den Überblick über die Array-Größe, um sich selbst:

size_t array_size = 5; 
int array[5] = {1, 2, 3, 4, 5}; 

// delete element at index 2 
memmove(array + 2, array + 3, (array_size - 2 - 1) * sizeof(int)); 
array_size--; 

In C++, aber es wäre besser, ein std::vector zu verwenden:

std::vector<int> array; 
// initialize array... 

// delete element at index 2 
array.erase(array.begin() + 2); 
+1

Bitte beachten Sie, dass memmove() nur für POD-Typen funktioniert, während OTOH fast jeden Typ mit einem Vektor verwendet werden kann, auch solche mit einem benutzerdefinierten Operator =(). –

0

Wenn Sie am meisten Sorgen über Code-Größe und/oder Leistung (auch für WCET-Analyse, wenn Sie eine brauchen), denke ich, dass dies wahrscheinlich sein wird einer der transparenten Lösungen (zum Auffinden und Entfernen von Elementen):

unsigned int l=0, removed=0; 

for(unsigned int i=0; i<count; i++) { 
    if(array[i] != to_remove) 
     array[l++] = array[i]; 
    else 
     removed++; 
} 

count -= removed; 
0

Nur so ist es zu beachten: Wenn die Anforderung der Elemente zu erhalten, um sie entspannt sind, ist viel effizienter, das Element zu ersetzen mit der zu entferne Letztes Element.

Verwandte Themen