C++ range-based for Schleife in einer Funktion

lprulzcrossover

Cadet 4th Year
Registriert
März 2014
Beiträge
71
Hey,

lernen grade in der Uni C++ (bisher nur C). Ich muss jede for-Schleife durch die range-based for-Schleife aus C++11 ersetzen.
Allerdings bekomme ich dabei einen Fehler, mit dem ich nichts anfangen kann. Ich nehme an dass es nicht geht, weil ja nur ein pointer auf das array übergeben wird und nicht das array selbst. Aber wie mache ich es dann?

Code:
void sort1(int num[], int start, int end) {
  bool finished = 0;

  while(!finished) {
    finished = 1;
    for(int i : num) { // hier ist die Fehleranzeige
      if(i > i+1) {
        swap(num, i, i+1);
        finished = 0;
      }
    }
  }
}

Ich hoffe hier ist ein Erfahrener unterwegs, der den Fehler schnell erkennt :D Danke jedenfalls schonmal.

Der Error:
error: no matching function for call to 'begin(int*&)'

Der ursprüngliche Code:
Code:
void sort1(int num[], int start, int end) {
  int finished = 0, i;

  while(!finished) {
    finished = 1;
    for(i=start ; i<end ; i++) {
      if(num[i] > num[i+1]) {
        swap(num, i, i+1);
        finished = 0;
      }
    }
  }
}
 
Zuletzt bearbeitet: (Ausgangscode hinzugefügt)
Rein interesse halber: Wie soll den Zeile 7 funktionieren?
In welchem Fall ist denn i größer als i+1?
 
Also so wie es in unserem Skript steht ist in der range-based for Schleife i das gleiche wie num, deswegen wird eigentlich num mit num[i+1] verglichen. Ich kann ja mal den ursprünglichen Code einfügen oben..
 
nein das stimmt so denke ich nicht (kenne die c++ variante nicht, nur von anderen sprachen) und da ist i = num[x] und wenn du jetzt i+1 machst, dann ist es das gleiche wie num[x]+1
 
Bei mir ist C++ auch schon lange her (aktuell Java) aber ich sehe das auch so:
i > i+1
ist nicht dasselbe wie
num > num[i+1]

Du greifst in ersten Fall auf den Wert von i zu und im zweiten tatsächlich auf die stelle i+1 in num[]
Du müsstest also weiterhin folgermaßen vergleichen:
i > num[i+1]
 
DocWindows schrieb:
Rein interesse halber: Wie soll den Zeile 7 funktionieren?
In welchem Fall ist denn i größer als i+1?
i nimmt den Wert des i-ten Eintrages des Arrays num an, sollte also korrekt sein. C++ ist bereits etwas her, aber muss nicht eine Referenz anstatt einer Kopie verwendet werden?
Code:
for (int& i : num ) {
 
Die Referenz müsste verwendet werden (so auch das Skript), wenn tatsächlich die Einträge vertauscht werden sollen. Da dies aber in der Funktion swap geschieht, sollte es hier mMn auch ohne Referenz gehen :)
Hatte es übrigens aber trotzdem mit Referenz probiert, ändert nichts an dem Problem^^
 
Deswegen bin ich mir nicht sicher, denn swap() wird i ja entweder als Kopie oder Referenz übergeben.
 
Achso ja, i wird als Kopie übergeben:
Code:
void swap(int num[], int i, int j) {
   int tmp = num[j];
   num[j]  = num[i];
   num[i]  = tmp;
}

Aber um den Inhalt der Schleife solls ja hier gar nicht gehen, sondern eher um den Kopf..
 
Range-based for funktioniert nicht mit einem Zeiger, und wenn du meinst, einer Funktion ein Array zu übergeben, übergibst du eigentlich einen Zeiger (auf das erste Element des Arrays).

Die Signatur:

Code:
void sort1(int num[], int start, int end);

ist äquivalent zu

Code:
void sort1(int* ptrToNum, int start, int end);

Es gibt leider keine Möglichkeit, mit nichts als einem Zeiger herauszufinden, wie viele Elemente das Array hat, auf das der Zeiger zeigt.
Ergänzung ()

Okay, strikt genommen gibt es einen Weg, aber dafür brauchst du ein Funktions-Template:

Code:
#include <cstddef>
#include <iostream>


template < typename ElementType, std::size_t N >
void printArrayMembers( const ElementType ( &theArray )[ N ] )
{
	for ( auto el : theArray )
	{
		std::cout << el << std::endl;
	}
}



int main()
{
	const int test[] = { 1, 2, 3 };

	printArrayMembers( test );
}

In diesem Beispiel weiß der Compiler auch innerhalb der printArrayMembers()-Funktion noch, wie groß das übergebene Array ist, da hier die Größe des Arrays ein Template-Argument ist.
Ergänzung ()

Noch mal ein P.S.:

Wenn ich's mir recht überlege, muß das eigentlich doch kein Template sein:

Code:
#include <cstddef>
#include <iostream>


void printArrayMembers( const int ( &theArray )[ 3 ] )
{
	for ( auto el : theArray )
	{
		std::cout << el << std::endl;
	}
}



int main()
{
	const int test[] = { 1, 2, 3 };

	printArrayMembers( test );
}

Aber so ist die Funktion natürlich nur auf ein int-Array der Größe 3 anwendbar, während die Template-Variante universell einsetzbar ist.
 
Zuletzt bearbeitet:
Danke! Die letzte Variante funktioniert 1A. Bin net drauf gekommen das array als Referenz zu übergeben :D
 
mal noch eine Frage meiner Seits. An dieser Stelle macht doch eine rangebase loop doch kein sinn, oder?
ich meine man will ja nur auf ein Teilbereich des arrays zugreifen (strart - end). Und eine rangebase loop geht doch immer alle Elemente durch. Und somit ist es doch Aufwendiger. Oder habe ich da ein Fehler in meinem Verständnis der Sache?
 
Die Frage von amoksep habe ich mir auch sofort gestellt.
sort1 schreit ja geradezu danach, dass ihr es rekursiv oder mehrfach für Untermengen der Daten aufrufen werdet und ein range-based for macht dann wirklich keinen Sinn da man start und end nicht verwenden kann.
Außerdem finde ich die Signatur ungewöhnlich: Wieso sind start und end (signed) ints? negative Index-Werte machen keinen Sinn beim Array-Zugriff.
Also mindestens "unsigned int" oder sowas wie uint32_t oder size_t.
Unschön finde ich auch finished vom typ int im original Code. Eine Variable die nur true oder false werden kann sollte wirklich ein bool sein - mindestens um jedem Quellcode-Leser zu verraten was sie bedeutet.

Und natürlich: Wieso ein plain-Array in C++. Dann auch noch im Zusammenhang von C++11 wo es doch std::array bzw als standard-container noch besser std::vector gibt, welche die selbe read/write performance haben. Solange man nicht gerade in der µC-Welt unterwegs ist und volatile Container wegen ISRs braucht haben Arrays in C++ eigtl. nix zu suchen.
 
Zuletzt bearbeitet:
Zurück
Oben