2010-01-26 3 views
9

OK, ich versuche, ein Sub-Array von einem bestehenden Array zu bekommen und ich bin mir einfach nicht sicher, wie es geht. In meinem Beispiel habe ich ein sehr großes Array, aber ich möchte ein Array aus den letzten 5 Elementen des Arrays erstellen.Was ist der beste Weg, um ein Sub-Array aus einem bestehenden Array in C++ zu erstellen?

Ein Beispiel von dem, was ich rede wäre:

int array1 = {1,2,3,...99,100}; 
int array2[5] = array1+95; 

Ich weiß, dass dies nicht richtig ist, aber ich bin einige Probleme, es richtig hinzubekommen. Ich möchte die Elemente 96 bis 100 in Array1 holen und sie in Array2 einfügen, aber ich möchte die Arrays nicht kopieren. Ich möchte nur, dass Array2 beim Element 96 beginnt, so dass Array1 [96] und Array2 [0] auf dieselbe Position zeigen.

+0

Denken Sie daran, dass Sie ein Sub-Array nicht technisch machen, indem Sie auf ein Element zeigen. – GManNickG

+0

Das 96. Element von 'array1' ist' array1 [95] '. Wenn du sagst "setze sie in array2", bedeutet das * kopieren, wie sonst wirst du sie in array2 einfügen? Es gibt keine Möglichkeit zu tun, was Sie wollen. Sie müssen entweder die Elemente kopieren oder einen Zeiger haben, der auf das 96. Element von 'array1' zeigt, oder ein Array von 5 Zeigern haben, und den Zeiger' i' auf das Element '95 + i' von' array1 zeigen lassen '. –

+0

Sie sind richtig, indem Sie "Array2" setzen, wollte ich nicht kopieren. Ich bedauere die Verwechslung in der Terminologie. –

Antwort

18

hierfür:

"such that array1[96] and array2[0] would be pointing to the same location." 

Sie tun können:

int *arr2 = arr1 + 96; 
assert(arr2[0] == arr1[96] == 97); 
+3

Das "behaupten" sollte ein Mathematiker sein, der behauptet, nicht C :-) –

+0

das funktioniert! Vielen Dank! –

+1

+1 für die einfache Lösung, die funktioniert. –

0

Sie sagten, Sie wollen nicht, um das Array zu kopieren, sondern einen Zeiger auf den letzten fünf Elemente erhalten. Sie haben es fast:

int array1[] = {1,2,3,...99,100}; 
int* array2 = &array1[95]; 
+0

als ich versuchte, dass ich diesen Fehler bekam: kann nicht von 'int *' in 'int []' konvertieren –

+1

'int array2 [] = array1 + 95;' ist illegal. –

+0

Sollte sein int array1 [] = {1,2,3, ... 99,100}; int * Feld2 = Feld1 + 95; Sie können ein Array (eckige Klammern) nicht mit einem Zeiger initialisieren - es kann angeben, wo es beginnt, aber nicht seine Größe. – BenG

1

in C++ Sie einen int-Zeiger als int Array verwenden können, so die array2 immer auf Artikel 96 in array1 zu starten ist einfach, aber es gibt keine Möglichkeit, ein geben array2 Größenbeschränkung, so können Sie dies tun

int array2 [] = & array1 [96];

oder diese

int *array2 = &array1[96]; 

aber nicht diese

int array2[5] = &array1[96]; // this doesn't work. 

Auf der anderen Seite, C++ nicht Array-Größenbeschränkungen ohnehin erzwingen, so dass der einzige wirkliche Verlust ist, dass man‘ t Verwenden Sie sizeof, um die Anzahl der Elemente in array2 zu ermitteln.

Anmerkung: &array1[96] ist das gleiche wie array+96

edit: Korrektur - int array[] = &array[96] nicht gültig ist, können Sie nur [] als Synonym für * verwenden können, wenn eine Funktion Parameterliste deklarieren.

so ist dies

erlaubt
extern int foo(int array2[]); 
foo (&array1[96]); 
+0

Ich bekomme immer noch einen Fehler, wenn ich versuche zu tippen: int array2 [] = & array1 [96].Der Fehler, den ich erhalte, ist: kann nicht von 'int *' zu 'int []' konvertieren –

+0

@John: 'int array2 [] = & array1 [96];' ist schlecht. –

+0

Ja, 'int foo []' und 'int * foo' sind nur als Funktionsparameter austauschbar. – jamesdlin

0
int array1[] = {1,2,3,...99,100}; 
int *array2 = &array1[96]; 
0
int arr[] = { 1, 2, 3, 4, 5}; 
int arr1[2]; 
copy(arr + 3, arr + 5, arr1); 
for(int i = 0; i < 2; i++) 
    cout << arr1[i] << endl; 

Der Code ist nicht sicher, wenn die Grenzen nicht richtig gehandhabt werden.

8

Ein Referenz Hack aus einem C-Programmierer bereit, das Typ-System zu untergraben, was zu bekommen funktioniert:

int (&array2)[5] = (int (&)[5])(*(array1 + 5)); 

Jetzt ein Array für alle Absichten und Zwecke array2 wird, und wird ein Sub-Array von array1 sein und wird sogar zu dieser berühmten C++ array_size Template-Funktion passierbar sein. Obwohl der beste Weg, mit diesem Hacker umzugehen, ist es, ihn mit mehr Hackerei zu verstecken!

#define make_sub_array(type, arr, off, len) (type (&)[len])(*(arr + off)); 

int (&array2)[5] = make_sub_array(int, array1, 5, 5); 

Schön. Schrecklich nach einigen Standards, aber das Endergebnis a) sieht ziemlich ordentlich aus, b) macht genau das, was Sie wollen, c) ist funktionell identisch mit einem tatsächlichen Array und d) hat auch den zusätzlichen Bonus (oder Fehlmerkmal) des Seins ein identischer Bezug zum Original, so ändern sich die beiden zusammen.

UPDATE: Wenn Sie möchten, eine Templat-Version (Art):

template <typename T, size_t M> 
T (&_make_sub_array(T (&orig)[M], size_t o))[] 
{ 
    return (T (&)[])(*(orig + o)); 
} 
#define make_sub_array(type, array, n, o) (type (&)[n])_make_sub_array(array, o) 

int (&array2)[5] = make_sub_array(int, array1, 5, 5); 

Wir haben noch den Typ zu übergeben. Da eines unserer Argumente als Teil der Besetzung verwendet werden muss, können wir das Makro nicht sauber (IMHO) vermeiden. Wir könnten dies tun:

template <typename T, size_t M, size_t N> 
T (&make_sub_array(T (&orig)[M], size_t o))[N] 
{ 
    return (T (&)[N])(*(orig + o)); 
} 

int (&array2)[5] = make_sub_array<int, 15, 5>(array1, 5); 

Aber das Ziel ist hier die Telefonvorwahl so sauber wie möglich zu machen, und dieser Anruf ist ein bisschen haarig. Die Pure-Macro-Version hat wahrscheinlich den geringsten Overhead und ist wahrscheinlich in diesem Fall am saubersten zu implementieren.

+1

Es ist so schlimm, es ist gut :-). +1. –

+0

Danke. Ich brauchte viel länger, weil ich wollte, dass es mit tatsächlichem C++ - Casting funktionierte, aber schließlich gab ich es auf und machte es _work_. Verbesserungen (vor allem eine mögliche Version von 'make_sub_array' als Template-Funktion - das habe ich auch schon eine Weile versucht, bevor ich aufgab). –

+0

@Chris: Mein C++ - Fu ist nicht toll, ich bin eher eine C-Person, aber ich werde es versuchen! –

3

Für einen völlig anderen Ansatz könnten Sie etwas wie tun.

vector<int> v0(array1 + 95, array1 + 100); 

oder

vector<int> v1(array1, array1 + 100); 
vector<int> v2(v1.begin() + 95, v1.end()); 

Dies würde eine echte Kopie der Elemente des Vektors machen.

+0

Sollte 'std :: vector sein 'für die Pendanterie. Wie auch immer, +1 für die meisten "C++" Antworten. –

3

Sie können boost::iterator_range verwenden, um „Scheiben“ von Arrays/Container darstellen:

#include <iostream> 
#include <boost/range.hpp> 

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

    // Create a "proxy" of array[5..7] 
    // The range implements the concept of a random sequence containter 
    boost::iterator_range<int*> subarray(&array[5], &array[7]+1); 

    // Output: 3 elements: 5 6 7 
    std::cout << subarray.size() << " elements: " 
       << subarray[0] << " " 
       << subarray[1] << " " 
       << subarray[2] << "\n"; 
} 

Beachten Sie, dass der Iterator Bereich „weiß“ über die Größe der Untergruppe. Es wird sogar Grenzen für Sie prüfen. Sie können diese Funktionalität nicht von einem einfachen Zeiger erhalten.

Die Nützlichkeit von Boost.Range wird deutlicher, sobald Sie etwas über STL-Container und Iteratoren erfahren.

Wenn Sie in der linearen Algebra, unterstützt Boost.uBlas Bereiche und Scheiben für seine Matrizen und Vektoren.

Verwandte Themen