CHAR kürzen bzw. formatieren

Von dem seriellen Port am Arduino Nano habe ich ein Char mit eingelesenen Daten. 14 Stellen.
ich benötige nur die Stellen 7 - 12 da die ersten 6 Zeichen Leerzeichen sind. Wie kann ich nur den Bereich 7 bis 12 in ein CHAR oder String kopieren?


char test[14] = {"abcdefghijklm"};
char text[8] = {'\0'};
byte zaehler;
void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  Serial.println(test);
  for (byte b = 6; b < 12; b++)
  {
    text[zaehler] = test[b];
    zaehler++;
  }
  Serial.println(text);
}
void loop()
{
}

Ein Char ist ein einzelnes Zeichen. Du hast eher ein Char-Array.
Woher weist Du, wann eine neue Übertragung beginnt?
Evtl. könntest Du die 6 Leerzeichen als Anfangserkennung nutzen (mitzählen) und den Rest in ein Array schreiben.

Gruß Tommy

https://www.nongnu.org/avr-libc/user-manual/group__avr__string.html

Basierend auf #2 und sscanf geht es auch so:

char test[14] = {"abcdefghijklm"};
char text[8] = {'\0'};
byte zaehler;
void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  Serial.println(test);
  sscanf (test, "%*6s%6s", text);
  Serial.println(text);
}
void loop()
{
}

Ich hab mal mein erstes noch erweitert...

char test[14] = {"abcdefghijklm"};
char text[8] = {'\0'};
byte zaehler;

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  Serial.print(F("zum teilen: "));
  Serial.println(test);
  for (byte b = 6; b < 12; b++)
  {
    text[zaehler] = test[b];
    zaehler++;
  }
  Serial.print(F("Variante 1 einzeln kopieren: "));
  Serial.println(text);
  Serial.println();
  Serial.print(F("Variante 2 mit Funktion kopieren: "));
  char *substart {test + 6};
  // strncpy(test, substart, 6);
  strncpy(text, substart, 6);
  Serial.println(text);
}
void loop()
{
}

Du meinst strncpy(text, substart, 6);.

1 Like

stimmt.

@DonCamillo
Da braucht es mehr Kontext, oder beser den ganzen Sketch.
Wozu erst 14 stellen lesen und dann einen Teil in eine andere Variable "kopieren"?

Du könntest ja beim Lesen einfach erst ab dem 7. Zeichen speichern, oder auch im Programm einfach die ersten 6 Zeichen nicht verwenden.

Aber wie gesagt, dazu wäre halt notwendig zu wissen was du genau machen willst.

Danke für eure Tipps...
Ich lese über den seriellen Port einen Datensatz ein. Der beginnt mit 6 Leerzeichen, den eigentlichen Daten und CR LF. Diese Daten werden dann an eine Anzeige gesendet. LED P10. Das alles funktioniert soweit. Nur werden die Leerzeichen auch an die Anzeige gesendet sodass diese Stellen an der LED - Anzeige leer bleiben. Wenn ich zum testen nur ein Leerzeichen sende, dann die Daten und CR LF funktioniert alles. Ich muss also nur die überflüssigen Leerzeichen entfernen.
Ich habe den Befehl Memmove auch schn einmal in einen anderen Projekt verwendet. Weis aber die genaue Funktion bzw. Programmierung nicht mehr :thinking:

Google defekt? Schau mal hier.

Gruß Tommy

Serial.print(6 + "      Datensatz\r\n");

Da noch immer unklar ist, was die Ausgangsbasis ist, hier dann eine weitere variante


String inputString = "          abcdefg     ";
void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  Serial.println(inputString);
  inputString.trim();
  Serial.println(inputString);
}

void loop()
{
}
`[code]



#include <SPI.h>
#include <DMD2.h>
#include <fonts/Arial_Black_16.h>

const int WIDTH = 2;                                    // Anzahl der Display (Breite)

const uint8_t *FONT = Arial_Black_16;                           //const uint8_t *FONT = Auswahl der Schrift für das Display

const char *MESSAGE = "     Display Version 1.4       9600 Baud 8 Bit no Parity    RS 485                   ";  // Definition des Starttext
const byte numChars = 14;                                                                    // Anzahl der auszuwertetenden Zeichen
char receivedChars[numChars];                                                                // char für die empfangenen Zeichen
char tempChars[numChars];                                                                    // char für temporäre Zeichen
char Gewicht[numChars] = {0};                                                                // char für Gewicht, [Zeichenanzahl wie numChar] und = {0}Inhalt 0
char Datensatz[20] = {0}; 
char rc [numChars] = {0};                                                                    // char für zusammengesetzte Daten mit einer Länge von 30 Zeichen und Inhalt 0
boolean newData = false;
boolean Error = false;
char Gewicht_1[8] = {'\0'};
SoftDMD dmd(WIDTH,1);                                                                        // DMD controls the entire display
DMD_TextBox box(dmd, 0,2);                                                                   // "box" provides a text box to automatically write to/scroll the display

//============

void setup() {
                                                                          
  dmd.setBrightness(200);                                                                    // setzen der Helligkeit auf 255 (Max)
  dmd.selectFont(FONT);                                                                      // Auswahl der Schriftart
  dmd.begin();                                                                               // Start SPI Anzeige
  const char *next = MESSAGE;                                                                // char "next" entspricht MESSAGE 
  while(*next) {
   box.print(*next);                                                                         // bei Neustart wird die MESSAGE angezeigt
   delay(100);
   next++;
   
}
Serial.begin(9600);                                                                         // Initialisierung serielle Schnittstelle mit 9600 Baud
}
//============

void loop() {
    recvWithStartEndMarkers();                                                               // Funktion "Empfang mit Start / Stopp Zeichen ausführen
    if (newData == true) {                                                                   // Wenn neue Daten ausgewertet worden bis zum Ende Zeichen
        strcpy(tempChars, receivedChars);                                                    // kopiere String "tempsChars" von "receivedChars"
        showParsedData();                                                                    // Funktion "showParsedData" ausführen
        newData = false;                                                                      // setze "newData" auf false
        Serial.print (ptr);
        Serial.print (tempChars);
                        
    }
  }

//============

void recvWithStartEndMarkers() {                                                             // Funktion "recvWithStartEndMarkers"
    static boolean recvInProgress = false;                                                   // setze "recvInProgress" auf false
    static byte ndx = 0;                                                                     // Byte "ndx" wird der Wert 0 zugewiesen
    byte startMarker = 0x20;                                                                 // byte "startMarker" ist 20Hex (Leerzeichen)
    byte endMarker = 0x0A;                                                                   // byte "endMarker" ist 0AHex (LF)
    char rc;                                                                                 // char "rc" ist für den Empfang der Daten

    while (Serial.available() > 0 && newData == false) {                                     // Schleife solange neue Daten verfügbar >0 ist und newData 0 false ist
        rc = Serial.read();                                                                  // schreibe Daten in char "rc"
                       
        if (recvInProgress == true) {                                                        // wenn recvInProgess 0 true ist...  Schleife ausführen
            if (rc != endMarker) {                                                           // wenn Daten in char "rc" kein Endzeichen (endMarker) enthalten
                receivedChars[ndx] = rc;                                                     // schreibe empfangenes Char (Formatierung Byte, Array mit Wert "ndx")in char "rc"
                ndx++;                                                                       // erhöhe den Array Wert "ndx" um 1
                if (ndx >= numChars) {                                                       // wenn der Array Wert "ndx" größer oder gleich des Byte "numChars" ist
                    ndx = numChars - 1;                                                      // wird der Array Wert Byte "ndx" auf den Wert "numChar" -1 gesetzt
                }
            }
            else {                                                                           // ELSE Bedingung für "recvInProgress" wenn der endMarker gefunden wurde
                receivedChars[ndx] = '\0';                                                   // dem char receivedChar Array wird 00HEX angefügt (terminiert)                      
                recvInProgress = false;                                                      // BOOL Wert recvInProgress wird auf false gesetzt
                ndx = 0;                                                                     // Array "ndx" auf 0
                newData = true;                                                              // neue Daten auf true
            }
        }

        else if (rc == startMarker) {                                                        // Wenn im char "rc" der Start Marker gefunden wurde
            recvInProgress = true;                                                           // setze "recvInProgress" auf true damit die einzelne Ausgabe der Daten von "rc" in das Array erfolgen kann s.o.
        }
    }
}


//============



void showParsedData() {

 
 const char *term = '\0';                                                                    // Terminierung
 //strncat (tempChars," ",9);
 strncat (tempChars, term,10);
 sscanf (tempChars, "%*6s%6s", Gewicht_1);
 Serial.println (Gewicht_1);
 //dmd.clearScreen();
 //dmd.drawString(8,2,Gewicht_1);
 //dmd.drawString(58,2,"t");
 

}
[/code]

Da ist der jetzige Code..`

Na ist doch was.
Wie gesagt, ich wollte nur wissen, was Du verwendest - String oder CharArray.
Ich hab mal was gebaut.
untgetestet - ich hab die dmd2 nicht und das muss jetzt mal blind gehen.

#include <SPI.h>
#include <DMD2.h>
#include <fonts/Arial_Black_16.h>

const int WIDTH = 2;                                    // Anzahl der Display (Breite)

const uint8_t *FONT = Arial_Black_16;                           //const uint8_t *FONT = Auswahl der Schrift für das Display

const char *MESSAGE = "     Display Version 1.4       9600 Baud 8 Bit no Parity    RS 485                   ";  // Definition des Starttext
const byte numChars = 14;                                                                    // Anzahl der auszuwertetenden Zeichen
char receivedChars[numChars];                                                                // char für die empfangenen Zeichen
char tempChars[numChars];                                                                    // char für temporäre Zeichen
char Gewicht[numChars] = {0};                                                                // char für Gewicht, [Zeichenanzahl wie numChar] und = {0}Inhalt 0
char Datensatz[20] = {0}; 
char rc [numChars] = {0};                                                                    // char für zusammengesetzte Daten mit einer Länge von 30 Zeichen und Inhalt 0
boolean newData = false;
boolean Error = false;
char Gewicht_1[8] = {'\0'};
SoftDMD dmd(WIDTH,1);                                                                        // DMD controls the entire display
DMD_TextBox box(dmd, 0,2);                                                                   // "box" provides a text box to automatically write to/scroll the display

//============

void setup() {
                                                                          
  dmd.setBrightness(200);                                                                    // setzen der Helligkeit auf 255 (Max)
  dmd.selectFont(FONT);                                                                      // Auswahl der Schriftart
  dmd.begin();                                                                               // Start SPI Anzeige
  const char *next = MESSAGE;                                                                // char "next" entspricht MESSAGE 
  while(*next) {
   box.print(*next);                                                                         // bei Neustart wird die MESSAGE angezeigt
   delay(100);
   next++;
   
}
Serial.begin(9600);                                                                         // Initialisierung serielle Schnittstelle mit 9600 Baud
}
//============

void loop() {
    recvWithStartEndMarkers();                                                               // Funktion "Empfang mit Start / Stopp Zeichen ausführen
    if (newData == true) {                                                                   // Wenn neue Daten ausgewertet worden bis zum Ende Zeichen
        showParsedData();                                                                    // Funktion "showParsedData" ausführen
        newData = false;                                                                      // setze "newData" auf false
        Serial.print (ptr);
        Serial.print (tempChars);
                        
    }
  }

//============

void recvWithStartEndMarkers() {                                                             // Funktion "recvWithStartEndMarkers"
    static boolean recvInProgress = false;                                                   // setze "recvInProgress" auf false
    static byte ndx = 0;                                                                     // Byte "ndx" wird der Wert 0 zugewiesen
    byte startMarker = 0x20;                                                                 // byte "startMarker" ist 20Hex (Leerzeichen)
    byte endMarker = 0x0A;                                                                   // byte "endMarker" ist 0AHex (LF)
    char rc;                                                                                 // char "rc" ist für den Empfang der Daten

    while (Serial.available() > 0 && newData == false) {                                     // Schleife solange neue Daten verfügbar >0 ist und newData 0 false ist
        rc = Serial.read();                                                                  // schreibe Daten in char "rc"
                       
        if (recvInProgress == true) {                                                        // wenn recvInProgess 0 true ist...  Schleife ausführen
            if (rc != endMarker) {                                                           // wenn Daten in char "rc" kein Endzeichen (endMarker) enthalten
                receivedChars[ndx] = rc;                                                     // schreibe empfangenes Char (Formatierung Byte, Array mit Wert "ndx")in char "rc"
                ndx++;                                                                       // erhöhe den Array Wert "ndx" um 1
                if (ndx >= numChars) {                                                       // wenn der Array Wert "ndx" größer oder gleich des Byte "numChars" ist
                    ndx = numChars - 1;                                                      // wird der Array Wert Byte "ndx" auf den Wert "numChar" -1 gesetzt
                }
            }
            else {                                                                           // ELSE Bedingung für "recvInProgress" wenn der endMarker gefunden wurde
                receivedChars[ndx] = '\0';                                                   // dem char receivedChar Array wird 00HEX angefügt (terminiert)                      
                recvInProgress = false;                                                      // BOOL Wert recvInProgress wird auf false gesetzt
                ndx = 0;                                                                     // Array "ndx" auf 0
                newData = true;                                                              // neue Daten auf true
                char *substart {receivedChars + 6};
                memset(tempChars, '\0', sizeof(tempChars));
                strncpy(tempChars, substart, 6);                                             // kopiere String "tempsChars" von "receivedChars"
                memset(receivedChars, '\0', sizeof(receivedChars));
            }
        }

        else if (rc == startMarker) {                                                        // Wenn im char "rc" der Start Marker gefunden wurde
            recvInProgress = true;                                                           // setze "recvInProgress" auf true damit die einzelne Ausgabe der Daten von "rc" in das Array erfolgen kann s.o.
        }
    }
}


//============



void showParsedData() {

 
 const char *term = '\0';                                                                    // Terminierung
 //strncat (tempChars," ",9);
 strncat (tempChars, term,10);
 sscanf (tempChars, "%*6s%6s", Gewicht_1);
 Serial.println (Gewicht_1);
 //dmd.clearScreen();
 //dmd.drawString(8,2,Gewicht_1);
 //dmd.drawString(58,2,"t");
 

}

Habe ich getestet. Funktioniert einwandfrei. Ich habe nur die Zeichenanzahl geändert. Zu meinen Verständnis wäre es gut zu Wissen wie es funktioniert. Im Char *substart stehen die Daten von receivedChars ab Pos. 6 oder steht der Pointer an Pos. 6?
Mit Memset wird tempChars terminiert, mit der Größe von tempChars, danach wird in tempChars die Daten von substart ab Pos. 6 mit einer Länge von 6 Zeichen kopiert? Anschließend wird receivedChars terminiert...

Gruß Camillo

Freut mich.
substart ist ein Zeiger, der auf die Position 7 zeigt. (lässt 6 hinter sich)
Mit memset wird das Array vollständig mit '\0' gefüllt.
Hintergrund ist, das sichergestellt werden muss, das wenn das Array neu befüllt wird immer ein '\0' am Ende vorhanden sein muss.
Mit strncopy wird in tempCars ab dem Pointer substart solange gelesen, bis entweder ein '\0' im Quellarray drin ist oder aber die 6 Zeichen gelesen sind.
Und hier kommt jetzt das memset zum tragen. Du könntest natürlich auch ein tempChars[7]='\0' setzen, aber Du weisst nicht, ob tatsächlich 6 Zeichen kopiert wurden....
Beim memset receivedChars verhält es sich genau so.

Im Elsezweig kann das receivedChars[ndx]='\0' eigentlich weg.

Vielen Dank für die Info. Ich habe es jetzt an der Anzeige getestet. Ich muss zu dem tempChars ein Leerzeichen anfügen damit das Display auch an dieser Stelle beschrieben wird (Leer). Habe den STRCAT verwendet, strcat (tempchar, ext).
ext habe ich " char ext = " "; " definiert, funktioniert aber nicht so recht. Da kommen wirre Zeichen im Display. Wie kann ich ein feste Leerzeichen anhängen?

Natürlich!
Es wird ein Zeiger erwartet, aber du gibst ein Zeichen.
Eigentlich müssen Warnungen kommen.
Aber die hast du wohl nicht aktiviert oder ignoriert.
Solltest du aber in deine Wahrnehmung einbeziehen.

Tipp:
Programmieren (C und auch C++) ist kein "ich wünsch mir was", sondern Arbeit, welche wenigstens etwas Sorgfalt und Disziplin erfordert.

Habe ich aus dem Netz:

char textA[10] = "abc";
char textB[5] = "xyz";

// haenge Zeichenkette textB an textA an
strcat(textA, textB);

Habe meine Zeile in char ext [1] = " "; geändert..