Kästchen im seriellen Monitor ? Funktion für "n mal Zeichen x" ?

Hallo, das ist mein allererster Post mit zwei Fragen:
1.: ich möchte einen String erzeugen, der aus einer vorgegebenen (aber veränderbaren) Anzahl gleicher Zeichen besteht, also z.B. 5 mal "x" oder 100 mal "x". Mit der Schleife im beigefügten Programm funktioniert das auch.
Gibt es auch eine Funktion, die das ohne Scheife macht ? Etwa so: ErzeugeString(Anzahl; "X").

2.: Die Ausgabe meines Programms erzeugt das gewünschte Ergebnis, allerdings mit 54 vorangestellten Quadraten. Sind das nichtdruckbare Zeichen ? Was erzeugt die ? Wie kann ich die vermeiden ?

void setup() {
  Serial.begin(9600);
  byte Breite = 10;
  String Links;
  long n = 0;  // Schleifenvariable
  for (n = 1; n < Breite+1; n++) {
    Links += "x";
  }
  Serial.print("Test1");
  Serial.print(Links);
  Serial.print("Test2");
}

void loop() {
}

Lass String weg und gib einfach das Zeichen n-mal in der Schleife aus. Eine Funktion dazu macht Dir das Leben leicht.
Als Parameter das Zeichen und die Anzahl.

??? vielleicht geht es um dass

Hier nicht:

23:06:22.613 -> Test1xxxxxxxxxxTest2

Ich hab mal den Code umgeschrieben.
Ergebnis das Gleiche.
Aber schöner.

void setup()
{
  Serial.begin(9600);
  const byte breite = 10;
  char buf[breite+1] = {'\0'};
  const char fillChar = 'x';
  memset(buf, fillChar, breite);
  Serial.print(F("Test1"));
  Serial.print(buf);
  Serial.println(F("Test2"));
}

void loop()
{
}

Hallo Klaus_ww,
du hast recht: wenn es nur um die einmalige Ausgabe geht, kann ich das Zeichen direkt in der Schleife ausgeben. Aber ich will das Ergebnis in einer Variablen aufbewahren, um es später nochmal zu verwenden.

Du verweist auf www.ascii-code.com.
Meine Angabe von 54 Kästchen ist wohl eher ein Zufall.
Ich habe das letzte print in ein println umgewandelt und den Sketch mehrfach auf den Arduino hochgeladen: Es kommen unterschiedlich viele (manchmal auch null) Kästchen, siehe Bildschirmfoto. Komisch.

[quote="my_xy_projekt, post:4, topic:1148435"]
Ich hab mal den Code umgeschrieben...[/quote]
"memset" scheint die Fundktion zu sein, die ich suche.
In der Referenz Arduino-Referenz - Arduino-Referenz finde ich sie nicht.
Bei Mouseover in der IDE kommt aber doch eine Info, aber sehrsehr knapp.
Wo gibt es dazu eine ausführlichere Beschreibung ?
Ich sollte noch sagen, dass ich mit der rduino-IDE 2.1.1 und Arduino Uno arbeite.

https://www.proggen.org/doku.php?id=c:lib:string:memset

Genaugenommen musst du in das letzte Byte noch eine 0 schreiben.
Das fehlt an @my_xy_projekt s Beispiel.
(Dort wird nur überflüssigerweise das erste Byte mit 0 vorbelegt)

Warum dein Versuch mit String nicht funktioniert, weiß ich allerdings nicht.
In Wokwi (Wokwi - Online ESP32, STM32, Arduino Simulator) gehts.

Jedenfalls mit 10 Zeichen Breite. Per String ist die maximale Breite erheblich kleiner als ohne.
Das macht es für eine wiederzuverwendende Funktion unschön.

was ist denn der echte Anwendungsfall für die 5 - 100 mal Füllzeichen? Wie nutzt du diese später genau und auf welchem Microcontroller?
Vieleicht gibts da was einfacheres, schöneres, schnelleres?

Das ist sicher nicht schneller, aber ohne rumgeschnörkel

void fill(uint16_t count, char c) {
  for (uint16_t i = 0; i < count; i++) {
    Serial.print(c);
  }
}

void setup() {
  Serial.begin(9600);
  byte Breite = 10;
  Serial.print("Test1");
  fill(10, 'x');
  Serial.print("Test2");
}
void loop() {}

zwar nicht "Gibt es auch eine Funktion, die das ohne Scheife macht ?" ... aber ich frag mich was an der Schleife in der Funktion böse sein soll. Die schreibst einmal und nutzt dann im Code die Funktion. Dafür gibts Funktionen.

Kann es sein, dass du gar keinen Arduino, sondern einen ESP verwendest?

Nein 100 % sicher Arduino UNO. Steht sogar drauf.

setz mal im setup als ERSTE Zeile

delay(500);

Du verwendest die IDE V2....
Ich würd mal sehen wollen, ob das mit der 1.8.19 auch so ist.
Die lässt sich parallel betreiben.
einfach als zip von der downloadseite runterladen, expandieren und in dem entpackten Arduino-Ordner einen neuen unterordner portable anlegen.
Dann die ide starten...

Der sollte bei einem Sketch wie

void setup() {
   Serial.begin(9600);
   Serial.println("Start");
}
void loop() {}

vor der Ausgabe "Start" nichts ausgeben. Weder direkt nach dem Hochladen, nach dem Start des SerialMonitor (was einen RESET auslöst) oder nach einem anschließenden RESET.

Das manchmal ist schon merkwürdig. Ich geh mal davon aus, dass an Pin1 (TX) nichts angeschlossen ist, was schon vor Serial.begin(9600); Dreck erzeugt.

Wie kommst Du da drauf?
Ich habe einen buffer mit 11 char.
Alle 11 char werden mit \0 initilisiert.
Dann werden 10 char mit x beschrieben.
Das Letzte bleibt mit \0 erhalten.

In diesem(!) Anwendungsfall ist die Länge bekannt. Es hätte bei der Initialisierung sogar das +1 entfallen können.
Ein Serial.print(buf) bringt dann noch immer 10 'x' raus.

Wie kommst du darauf?
char buf[11] = {'\0'}; // reserviert einen Speicherbereich von 11 Byte und füllt buf[0] mit 0.
Der Rest ist, bei einer lokalen Variablen auf dem Stack zumindest, undefiniert.
[ Nachtrag ]@my_xy_projekt
Hatte ich so gedacht...
Aber nochmal ausprobiert:

char buf1[11]; // reserviert (als lokale Variable) undefinierte 11 Byte
     buf1[0] = 0x01; // verändert nur dieses eine Byte
char buf2[11] {0x01}; // reserviert weitere 11 Byte und füllt diese mit 0x01, 0x00 , 0x00 ... 

Jedenfalls beim avr-gcc Compiler in der IDE 1.8.19.
Ob das eine definierte Spracheigenschaft von C++ ist, oder ob es formal undefiniert ist, lass ich jetzt mal so stehen.
Ich meine gesehen zu haben, dass uninitialisierte oder initialisierte lokale Variable einen Einfluss auf die Reihenfolge auf dem Stack haben. Das ist sicher im Belieben des Compilers.
Dass die Initialisierung einer Variablen
int i = 0;
etwas anderes ist als
int i; i=0; // ruft den Zuweisungsoperator auf
habe ich schonmal schmerzlich lernen müssen.

Jedenfalls Danke @my_xy_projekt, dass du mich zum Rumfummeln verleitet hast.

Ich will mich in die Arduino-Programmierung reinarbeiten und habe mir ein Projektchen vorgenommen: Mein allererstes Programm nachbauen, das ich damals für einen Textmonitor gemacht habe:

Rennstrecke mit Seitenrand wird durch Zeilen simuliert, :
|-------O-------|, wobei O das Auto ist
. |------O--------| Ein Zufallsgenerator verändert die Strecke durch Änderung der
.. |-----O---------| Anzahl der führenden Leerzeichen und Striche neben dem Auto.
Durch neue Zeilen unten am Bildschirm wandern die alten Zeilen nach oben: Eindruck einer kurvigen Straße.
Durch Tastendruck (links, rechts) kann der Spieler gegenhalten.
Wenn Position "|" = "O", dann Crash.

Grafisch ziemlich primitiv, aber wir hatten eine ganze Weile ziemlich Spaß mit dem Autorennen.
Dafür brauche ich Variablen mit unterschiedlich vielen Zeichen drin:
Leerzeichenfolge, "|", Linke_Straßenseite, "O", Rechte_Straßenseite, "|".

1 Like

Danke für die vielen Vorschläge :slightly_smiling_face:. Ich werde vermutlich ein paar Tage brauchen, bis ich alles ausprobiert habe.

dann würde ich mir aber nur einfach eine Funktion schreiben die 3 Parameter bekommt:

  • blanks am Anfang
  • position des Autos
  • breite der Straße (damit du auch engstellen mal machen kannst.

noch ohne crash am Rand:

Genau das richtige für den SerialMonitor.
Kannst du auch auf dem SerialPlotter und der Ausgabe von 3 Werten je Zeile "vollgrafisch" darstellen.

1 Like