For each (wie komme ich an den index)

Hallo,
ich spiele gerade was mit for each Schleifen rum :wink:
Dabei hat dann was nicht geklappt , ich hab das jetzt mal auf ein ganz einfaches Beispiel runter gebrochen. So wie ich das im Moment sehe geht das so auch nicht. Problem ist eigentlich wie komme ich an den Index damit ich den z.B für b [index] nutzen kann.

Heinz

int a[]={10,20,30,40,50};
int b[]={100,200,300,400,500};

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

 for(auto &elm :a){
 Serial.print(elm); Serial.print("  ");
 Serial.println(b[elm]); // das kann ja so nicht stimmen
 }
}
void loop() {
  // put your main code here, to run repeatedly:
}

Wie immer:

 Serial.println(b[elm-1])

Sorry du das mich nicht verstanden , in dem Array a könnte auch ganz was anderes stehen, das soll nicht der Index sein

Wenn Sie die Range-based for loop verwenden, haben Sie keinen Index

Aah... ok.
Du willst den Index und nicht den Inhalt... .. steht ja so auch in der Frage ;(

Ja damit ich damit auf was anderes zugreifen kann , im Beispiel halt auf b
ich hab dazu folgendes gefunden

https://www.learncpp.com/cpp-tutorial/for-each-loops/
Since C++20, range-based for-loops can be used with an init-statement just like the init-statement in normal for-loops. We can use the init-statement to create a manual index counter without polluting the function in which the for-loop is placed.

@J-M-L ja es wird wohl nicht gehen
Gruß Heinz

void setup()
{
  // put your setup code here, to run once:
  Serial.begin(115200);
  uint16_t elmNumb = 0;
  for (auto &elm : a)
  {
      Serial.print(elmNumb); Serial.print("  ");
      Serial.print(elm); Serial.print("  ");
      Serial.println(b[elmNumb]); // das kann ja so nicht stimmen
      elmNumb++;
  }
}

:wink: - vielleicht nicht ganz ernst zu nehmen, aber das wäre meins, wenn ich was neues ausprobieren müsste...

1 Like

Hallo,
ja ok das geht auch , dann bleib ich aber lieber bei einer normalen for schleife und nutze sizeof() um an die max Anzahl zu kommen.
Gruß Heinz

Ja, das funktioniert nur mit C++ 20 und Arduino ist in dieser Version nicht ...

const byte data[] = {0, 1, 2, 3, 4, 5};

void setup() {
  Serial.begin(115200);
  for (int i = 0; auto& d : data) { // Error 
    Serial.println(d);
    i++;
  }
}

void loop() {}

aber Sie können es immer so schreiben, wenn Sie den Index brauchen ...

const byte data[] = {0, 1, 2, 3, 4, 5};

void setup() {
  Serial.begin(115200);
  int i = 0;
  for ( auto& d : data) {
    Serial.println(d);
    Serial.println(data[i]);
    i++;
  }
}

void loop() {}

(aber in diesem Fall können Sie genauso gut eine traditionelle "for-loop" machen ...)

2 Likes

Ok, bin ich nicht allein mit dem Hilfsmittel :slight_smile:

Ich würde das "range-based for-loops" nicht verwenden und einfach tun

const byte data[] = {0, 1, 2, 3, 4, 5};

void setup() {
  Serial.begin(115200);

  for (size_t i = 0; i < sizeof data / sizeof * data; i++) {
    Serial.println(data[i]);
  }
}

void loop() {}

@Rentner Das ist sogar gefährlich.
Du benutzt zwei getrennte Arrays. Wenn das Erste mehr Elemente hat, als das Zweite, fliegt Dir das um die Ohren.

Es muss mindest einePrüfung rein, das b genügend Elemente hat.
Ansonsten: zweidimensional....

Moin @my_xy_projekt , apropos "Neues ausprobieren":

Ich bin inzwischen ein Fan der "Streaming.h" Lib. Wenn Du die inkludierst, kannst Du das Obige ohne Weiteres(!) wie folgt schreiben:

 #include "Streaming.h"

Serial << elmNumb << "   " << elm << "   " << b[elmNumb]) << "\n";
// oder
Serial << elmNumb << "\t" << elm << "\t" << b[elmNumb]) << "\n";



Geht auch mit anderen Stream-basierenden print-Funktionen (lcd, tcp, ...).

Ich weiss...
...kann nicht voraussetzen, das jeder andere das auch hat.
Meine V: 6.0.9 - aufgenommen am 18.8.2021

1 Like

Der "range based for loop" ist dafür gemacht, um mit Iteratoren arbeiten zu können.
Es ist KEINE zählende Schleife.
Also gibt es auch keinen Index.

Brauchst du einen Index?
Dann ist diese Schleife falsch, für deine Anwendung.

Hallo,
@combie nach unserer gestrigen Fleisch und Blut Überlegung wollte ich das mit dem Üben mal in Angriff nehmen :joy: Falscher Ansatz
Gruß Heinz

Dann ist doch Gut!
Ein erkannter Irrtum, ist schon ein wichtiger Schritt!

Ist dir das Konzept: Iterator bekannt?
Denn das ist wirklich Übenswert!

nein , Wikibooks ist schon angeworfen

Ja!

Wobei viele "Bücher" da gerne die UrUrUrGrundlagen vergessen.
Und die finden sich schon in Babylon, auf Tontäfelchen gekratzt.
Die ollen Griechen haben sich damit beschäftigt.
Und wir kennen das Wort "iterieren" aus dem Lateinischen.

Im Grunde beschreibt es die abstrakte Idee, dass es "fortschreitende" Prozesse in diesem Universum gibt.
z.B. hat das Wort UrUrUrGrundlagen schon 4 Iterationsstufen hinter sich, bis zum Heute.

Das mit dem Iterieren ist also keines falls irgendwie neu oder überraschend.

Das einzige neue daran ist, zumindest in C++:

Damals, als es nur die alten schleifen gab, hatten "wir" oft einen Container/Array, sind mit einer Schleife darüber hinwegiteriert, und haben im Schleifenkörper einen Code/Algorithmus ausgeführt.

Diese 3 Elemente waren zusammengehörig.
Datenbasis Iteration Algorithmus

Die werden jetzt und hier voneinander getrennt.
Als einzelne, austauschbare Dinge betrachtet.

Idealer Weise führt uns das dazu, dass man einen Algorithmus auf jedem Container anwenden kann. Es muss einen nicht interessieren, ob das ein Baum, eine Liste, oder ein Array ist.
Es müssen noch nicht einmal reale Daten sein.

Hier mal, wie man über einen "Bereich" eines Arrays hinweg iterieren kann.
Dürfte so ziemlich die einfachste "Iterator Sache" sein.
Operatoren müssen wir dafür nicht bauen, da die verwendeten Pointer das schon haben.

#include <Streaming.h> // die Lib findest du selber ;-)
Print &cout = Serial; // cout Emulation für "Arme"


template<typename FeldType>
class Bereich // Teilbereich eines Arrays Bereich<Type>(von,bis)
{
  private:
  FeldType *start, *ende;
  public:
  Bereich(FeldType *feld, unsigned startIndex ,unsigned  anzahl): start(feld+startIndex), ende(feld+startIndex+anzahl){}
  FeldType *begin(){return start;}
  FeldType *end()  {return ende; }
};


int feld[] {1,77,4,7,3,9,2,0,4}; // ein ganz normales unsortiertes Array

void setup() 
{
  Serial.begin(9600);
  cout << F("Start: ") << F(__FILE__) << endl;

  // Bereich ausgeben ab 3te Element, 2 Elemente
  for(auto d:Bereich<int>{feld,2,2}) cout << d << ' ';
  cout << endl;
}

void loop() 
{

}

Ausgabe: "4 7"

Hallo
vielen Dank für das Beispiel, das hab ich im wesentlichen verstanden. Allerdings muss ich über den Sinn des Ganzen und die Möglichkeiten und Vorteile dazu noch mal in mich gehen. Wenn mich mal was packt geb ich so schnell nicht auf.
Heinz