foreach-Schleife mit Übergabeparametern

Hallo,

ich habe folgende function:

bool text_is_number(const char text[], int& value)
{
	bool result = false;

	value = 0;

	if ((text != NULL) && (strlen(text) > 0))
	{
		result = true;

		for (size_t i = 0; i < strlen(text); i++)
		{
			if (!isDigit(text[i]))
			{
				result = false;

				break;
			}
		}

		if (result)	value = atoi(text);
	}

	return result;
}

Diese function wollte ich testweise auf eine foreach-Schleife umschreiben:

bool text_is_number_2(const char text[], int& value)
{
	bool result = false;

	value = 0;

	if ((text != NULL) && (strlen(text) > 0))
	{
		result = true;

    for (auto c : text)
    {
      if (!isDigit(c))      
			{
				result = false;

				break;
			}
    }

		if (result)	value = atoi(text);
	}

	return result;
}

Dann bekomme ich aber beim Compilieren folgende Fehlermeldungen:

sketch.ino: In function 'bool text_is_number_2(const char*, int&)':
sketch.ino:37:19: error: 'begin' was not declared in this scope
for (auto c : text)
^~~~
sketch.ino:37:19: note: suggested alternative: 'rewind'
for (auto c : text)
^~~~
rewind
sketch.ino:37:19: error: 'end' was not declared in this scope
sketch.ino:37:19: note: suggested alternative: 'rand'
for (auto c : text)
^~~~
rand

Error during build: exit status 1

Um generell eine foreach-Schleife zu testen, hab ich Folgendes getestet, das auch funktioniert.

  char type[11] = "sketch";

  Serial.println(type);

  for(char c:type)
  {
    if (c == NULL)
      break;

    Serial.println(c);    
  }

  Serial.println(type);

Es liegt also an der umgeschriebenen function an den Übergabeparametern.
Was müsste man ändern, damit eine foreach-Schleife auch mit den Übergabeparametern funktioniert?

Also das Konstrukt for (auto x:y) {} ist keine "for each" Schleife, sondern eine "Range based" Schleife. Diese "Range" geht aber bei der Übergabe an eine Funktion verloren, weil in der Funktion nur noch der Zeiger auf den Anfang des Arrays ankommt.

Bei Deinem Test ist das Array global verfügbar. Dann funktioniert das. Oder wenn das Array in der Funktion definiert würde.

Also so, wie Du das vor hast, funktioniert das nicht. Allenfalls auf ESP Controllern kann man die STL Varianten array und/oder vector verwenden. Da klappt das dann wieder. Da gibt es auch eine "echte" for_each()" Schleife.

ah ok - Danke für die Erklärung

Für Arrays baut der Compiler Iteratoren.
Für Strings(und andere exotische Container) muss man selber welche bauen.

class StringIterator
{
  private:
  char *ptr;
  
  public:
  StringIterator(char *ptr):ptr{ptr}{}
  char *begin() {return ptr;}
  char *end()   {return strlen(ptr)+ptr;}
};

void test(char str[])
{
  for(char c:StringIterator{str})
  {
    if (isDigit(c)) Serial.println(c);
      else break;
  }
}

void setup() 
{
  Serial.begin(9600);
  char st[] = "4567dghjzj";
  test(st);
}

void loop() 
{

}

Wenn du nur einen Zeiger auf den Text übergibst, funktioniert das Iterieren deines for"each" nicht.
Aber es gibt in C/C++ ja auch while-Schleifen:

bool text_is_number(const char* text, int& value) {
    bool result = false;
    value = 0;
	if ((text != NULL) && (*text != 0)) {
           result = true;
           const char* t = text;
           while (*t) {
      	       if (!isDigit(*t++))	{
                    result = false;
                    break;
               }
           }
           if (result)	value = atoi(text);
   }
   return result;
}

Leer- und Minus-Zeichen sind --wie bei dir-- verboten.