dreistelligen Zahl mit führenden Nullen

Quelle1: Adafruit "Music Maker" MP3 Shield - #4 by tiggerson - Deutsch - Arduino Forum
Quelle2: Adafruit "Music Maker" MP3 Shield - #8 by Serenifly - Deutsch - Arduino Forum

Aufgabe: Erzeugen eines Dateinamens der Form 5.3 mit Präfix „t“, einer dreistelligen Zahl mit führenden Nullen und dem Suffix „.mp3“.

Der Compiler versteht den Code und ich bin mit der Funktion zufrieden:

    int nummer = random(anzahl + 1); // Zufallsnummer erzeugen zwischen 1 bis anzahl
    char track[9] = { 0 };
    strcat_P(track, PSTR("t000"));
    if (nummer < 10) {
      itoa(nummer, track + 3, 10);
    }
    else if (nummer < 100) {
      itoa(nummer, track + 2, 10);
    }
    else {
      itoa(nummer, track + 1, 10);
    }
    strcat_P(track, PSTR(".mp3"));
    if (debug =="j") Serial.println(track);
    musicPlayer.startPlayingFile(track); // Lied beginnt

Sehen die Experten mögliche Probleme zur Laufzeit?

Anmerkungen: Mein Geschenk sollte möglichst funktionieren. Wenn ich die größere Speicherkarte habe, können auch dreistellige Zahlen < 800 vorkommen.

Projekt_MP3_Arduino.ino (3.36 KB)

Wenn es funktioniert musst du auch nichts optimieren. Wird ja nicht oft aufgerufen

Wenn du kompakten Quell-Code willst, würde sich snprintf() anbieten. Damit kann man das in einer Zeile erschlagen. Der Flash Verbrauch ist zwar ziemlich hoch, aber das ist nicht schlimm wenn man noch Platz hat.

char track[9];
snprintf_P(track, sizeof(track), PSTR("t%03d.mp3"), random(1, 53));

Hallo und danke für die schnelle Antwort! Mir geht es um Laufzeitprobleme, ob beispielsweise ein Array anderen Speicher überschreibt. Wenn das nicht der Fall ist, kann ich mich der Erweiterung widmen, bin ja noch nicht fertig.

ob beispielsweise ein Array anderen Speicher überschreibt

Dein Array ist 9 groß. Das reicht für 8 Zeichen. Sollte also eigentlich passen. Man kann solche temporären Puffer auch etwas größer machen als eigentlich nötig wenn man etwas Spielraum möchte.

Sicher wäre hier auch snprintf(). Das schreibt nicht über das Array hinaus. Wobei der String im Fehlerfall allerdings nicht korrekt terminiert ist, da er bist in die letzte Stelle schreibt und kein Platz mehr für NULL ist.

Übrigens, wegen Debug Ausgaben auf Serial:

#define DEBUG

#ifdef DEBUG
        #define debugPrint(text) Serial.print(text)
	#define debugPrintln(text) Serial.println(text)
#else
	#define debugPrint(text)
        #define debugPrintln(text)
#endif

Das wird schon beim Kompilieren festgelegt. Wenn man keine Debug Ausgaben hat, kommentiert man "#define DEBUG" aus. Dann werden die dann erst gar nicht übersetzt, der Code wird kleiner und man muss man keine Abfrage zur Laufzeit machen.

Das funktioniert:

#ifdef DEBUG
    Serial.println(F("Adafruit VS1053 Library Test"));
#endif

Das funktioniert nicht:

#ifdef DEBUG
  #define debugPrintln(text) Serial.println(F("Adafruit VS1053 Library Test"))
#else
  #define debugPrintln(text) 
#endif

Habe ich was falsch verstanden?

Ja. Du verstehst nicht was das Makro macht. Das ersetzt vor dem Kompilieren den Text "debugPrintln" durch "Serial.Println". Aber nur wenn das #define gesetzt ist.

Du machst deine Debug Ausgabe so:

debugPrintln(F("Adafruit VS1053 Library Test"));

Wenn du dann die Zeile #define DEBUG auskommentierst, wird das nicht kompiliert, da er das dann durch nichts ersetzt.

Dadurch muss man nicht in jede Zeile #ifdef #endif schreiben.

Serenifly:
Du verstehst nicht was das Makro macht.

:-[ Aber ich bleibe dran:

#ifdef DEBUG
  #define debugSerBegin(text) Serial.begin(text)
  #define debugPrint(text) Serial.print(text)
  #define debugPrintln(text) Serial.println(text)
#else
  #define debugSerBegin(text)
  #define debugPrint(text)
  #define debugPrintln(text)
#endif
...
  debugSerBegin(9600);
...
  debugPrintln("Adafruit VS1053 Library Test");

Funktiomieren tut es wohl, aber ich bin unsicher wegen "text" und "9600".

Das ist eine ganz einfache Text-Ersetzung. Eine Typ-Überprüfung findet da nicht statt. Die Parameter heißen halt "text". Du kannst genauso "args" schreiben.

Und wenn du mehrere Argumente brauchst (für Formatierungen wie HEX oder BIN) macht man das:

#ifdef DEBUG
  #define debugPrint(...) Serial.print(__VA_ARGS__)
  #define debugPrintln(...) Serial.println(__VA_ARGS__)
#else
  #define debugPrint(...)
  #define debugPrintln(...)
#endif

Variadische Makros :slight_smile:

Dann geht auch das:

debugPrintln(4569, HEX);

Das übernehme ich in mein Standard Repertoire. Vielen Dank!