www.mikrocontroller.net

Forum: Compiler & IDEs Anfängre string zerlgen


Autor: Dennis S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo ich arbeite gerade an einem kleinen Projekt für meinen 
Professor.Leider bin ich noch recht neu im Umgang mit C.Darum bitte ich 
um Entschuldigung für mein Unverständnis.Hier mein Problem ich bekomme 
einen String z.b "34,567,55,77". Diesen soll ich nun anhand der Kommas 
zerlegen und zwischenspeichern für eine spätere Verarbeitung.
Besetn dank schon mal für die Hilfe.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
strtok

Autor: Dennis S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab ich mir auch schon angeschaut.Nur wie speichere ich dann meine 
einzelnen Werte ab für die weiter Verarbeitung?

Autor: Thomas Burkhart (escamoteur)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ähm, sollst Du die Zahlenwerte speichern oder die Stringschnipsel?

Gruß
Tom

Autor: Dennis S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Stringschnipsel.Diese soll ich später mit einer hinterlegten Liste 
verkleichen und einzelne Funktionen dadurch aufrufen.
Gruss Dennis

Autor: Thomas Burkhart (escamoteur)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Weißt Du von vorneherein wie viele Einträge der String hat? Bzw. wie 
lang die einzelnen Schnipsel werden können?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dennis S. schrieb:
> Die Stringschnipsel.Diese soll ich später mit einer hinterlegten Liste
> verkleichen und einzelne Funktionen dadurch aufrufen.

Das kommt jetzt drauf an.

strtok ermöglicht dir 2 Arten der Weiterverwendung

Die eine ist: du kopierst die Einzelteile in neue Strings um (also 
jeweils in eigene char Arrays)

Die andere ist: strtok hinterlässt den String in einer Form, dass man 
Pointer in den Originalstring als neue Stringanfänge bekommt, so dass 
man dem weiterverabeitende Programm auch hier ein 'Array von Strings' 
unterjubeln kann, welches in Wirklichkeit nur aus Pointern in ein und 
denselben String besteht.

Hier hat man also gewisse Freiheiten, um sich an der Weiterverarbeitung 
der Einzelteile zu orientiern und die Verwendung von strtok daran 
anzupassen.

Autor: Dennis S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der String besteht im moment aus 4 Teilen diese können einzelnd bis zu 
20 Zeichen enthalten.Kann sein das da aber noch mehr hinzukommt.

Autor: Thomas Burkhart (escamoteur)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> welches in Wirklichkeit nur aus Pointern in ein und
> denselben String besteht.

Hatte ich auch schon überlegt. Kommt halt drauf an, ob der Orginalstring 
erhalten bleibt.

Wäre schon elegant. Dann kann er aber auch einfach den String 
durchlaufen und bei jedem Komma einen neuen Pointer setzen und das Komma 
durch eine \0 ersetzen.

Autor: Dennis S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich denke ich würde die einzelnen Teile in neue Strings kopieren.Ist für 
mich glaube ich dann erst mal einfacher zu verstehen.
Besten dank schon mal für die Hilfsbereitschaft hier.

Autor: Thomas Burkhart (escamoteur)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zwei Möglichkeiten:

1.
Mach ne verkettete Liste mit je einem Eintrag für jeden Substring der 
Dynamisch allokiert wird, dann bist Du super flexibel und verbrauchst 
nicht unnötig Speicher.

2. Ermittle zuerst wie viele Einträge der Orginalstring hat und die groß 
der längste davon ist und allokier ein array char[length][size] und trag 
da die Schnipsel ein. Ist natürlich je nachdem wie groß die Länge der 
Einträge scwankt etwas Speicherverschwendung.

Gruß
Tom

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas Burkhart schrieb:
> Karl heinz Buchegger schrieb:
>> welches in Wirklichkeit nur aus Pointern in ein und
>> denselben String besteht.
>
> Hatte ich auch schon überlegt. Kommt halt drauf an, ob der Orginalstring
> erhalten bleibt.
>
> Wäre schon elegant. Dann kann er aber auch einfach den String
> durchlaufen und bei jedem Komma einen neuen Pointer setzen und das Komma
> durch eine \0 ersetzen.

Ja, klar.
strtok hat ein paar (für manche Zwecke) unangenehme Eigenschaften. zb 
werden mehrere hintereinderliegende gleiche Trennzeichen übersprungen. 
Das kann manchmal gewollte sein (wenn es zb gilt die Trennung über 
Leerzeichen zu machen) ist aber manchmal ein echter Show-Stopper.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dennis S. schrieb:
> Ich denke ich würde die einzelnen Teile in neue Strings kopieren.Ist für
> mich glaube ich dann erst mal einfacher zu verstehen.

Das kommt drauf an.
Stringhandling in C, mit Strings deren Länge man im Vorraus nicht kennt, 
ist eine recht unangenehme Sache.

Autor: Dennis S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hatte mir überlegt ein Struct zu erstellen.Dort einzelne arrays zu 
erstellen und die Torken diesen dann zuzuweisen.

Autor: Dennis S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei meinem Programm ist nur ein Trennzeichen vorgesehen.Denke mal die 
einzelnen Teilsstrings werden nicht grösser als 30-40 Zeichen was ich so 
rausgehört habe.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aber um mal etwas Leben in die Bude zu bekommen
#include <stdio.h>
#include <string.h>

int main(void)
{

  {
    // einfach einen Token nach dem anderen ausgeben.
    // Das benutzt man wenn man nicht alle token in einem Rutsch braucht
    char string[] = "command,arg1, arg2";
    char *token;
    token = strtok( string, ", " );   // zerlegt wird an , und Leerzeichen
    while( token != NULL )
    {
      printf( "%s\n", token );
      token = strtok( NULL, ", " );        /* weitere Token ermitteln */
    }
  }
  
  printf( "\n\n" );

  {
    // hier werden alle Token zwischengespeichert (Pointer in den Originalstring)
    // das braucht man, wenn zb eine Funktion aufgerufen wird, die alle
    // Token auf einmal braucht
    char string[] = "command,arg1, arg2";
    char *token;
    char* tokens[20];
    int   nrTokens = 0;
    int   i;
    
    token = strtok( string, ", " );   // zerlegt wird an , und Leerzeichen
    while( token != NULL )
    {
      tokens[nrTokens++] = token;
      token = strtok( NULL, ", " );        /* weitere Token ermitteln */
    }

    for( i = 0; i < nrTokens; i++ )
      printf( "%s\n", tokens[i] );
  }
  
  return 0;
}

Autor: Remote One (remote1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für mein Handy-Projekt lese ich empfangene SMS aus und suche nach 
bestimmten "Command Strings"

Dazu habe ich mir eine  struct gebaut:
typedef struct SMS_CMD_LIST_S{
  char cmd[10];        /**< Zeichenkette für Kommando */
  uint8_t (*fp)(uint8_t dat);  /**< Funktionspointer auf Funktion, welche Kommando \ref cmd zugeordnet werden soll */
}SMS_CMD_LIST_T;

const SMS_CMD_LIST_T sms_cmd_list[] = {
  {"set",sms_cmdset}
};

Den empfangenen String durchsuche ich ebenfalls mit strtok. Mit Hilfe 
von qsort und bsearch vergleiche ich dann mit dem Kommand string:
#define SMS_DELIMITER ",;: "

// Kommando aus empfangener SMS auslesen
char *ptr_nachricht;
char nachricht[161];  // strtok verändert string --> Kopie anlegen
SMS_CMD_LIST_T keyItem = {"",NULL};
strcpy(nachricht,sms_dec_data.nachricht);
//nachricht in Kleinbuchstaben umwandeln
ptr_nachricht = nachricht;  // Startadresse übergeben
while(*ptr_nachricht){
  if (*ptr_nachricht >= 'A' && *ptr_nachricht <= 'Z') {
    *ptr_nachricht = *ptr_nachricht - 'A' + 'a';
  }
  ptr_nachricht++;
}
// sortieren der Befehlsliste (Voraussetzung für bsearch)
char *tmp;
qsort(&sms_cmd_list, (sizeof(sms_cmd_list)/sizeof(SMS_CMD_LIST_T)), sizeof(SMS_CMD_LIST_T), (int(*)(const void*,const void*))strcmp);
ptr_nachricht = strtok_r(nachricht,SMS_DELIMITER,&tmp);  // ersten Befehl extrahieren
while (ptr_nachricht!=NULL){
// Befehle entsprechend Liste ausführen
  strcpy(keyItem.cmd,ptr_nachricht);  // gefundenes Kommando übergeben
  SMS_CMD_LIST_T* spItem = (SMS_CMD_LIST_T*)bsearch (&keyItem, sms_cmd_list, (sizeof(sms_cmd_list)/sizeof(SMS_CMD_LIST_T)), sizeof(SMS_CMD_LIST_T), (int(*)(const void*,const void*)) strcmp);
  if (spItem != NULL) { spItem->fp(0); }
  ptr_nachricht = strtok_r(NULL,SMS_DELIMITER,&tmp);  // neues Kommando suchen (falls mehrerer vorhanden sind)
}


Wenn ich das richtig verstanden habe, sollte das genau das sein was du 
suchst. Schaus dir einfach mal an (inklusive der reference zu den 
einzelnen Funktionen)

Autor: Dennis S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Besten dank werde es jetzt mal mit deiner 2 Lösung versuchen.Geb dann 
noch mal ne Rückmeldung.

Autor: Dennis S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mein Programm läuft soweit.Besten Dank noch mal an alle.

Autor: Thomas Burkhart (escamoteur)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie hast Du es denn jetzt gelöst?

Autor: Dennis S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich teile meinen String mit strtok auf und kopiere dann die Daten mit 
strcpy auf meinene im strcut festgelegten Parameter.

Besten dank noch mal für die tolle Hilfe hier.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dennis S. schrieb:
> Ich teile meinen String mit strtok auf und kopiere dann die Daten mit
> strcpy auf meinene im strcut festgelegten Parameter.

Wo kommt der Originalstring her?

Besteht die Möglichkeit, dass der String fehlerhaft ist?
Wenn den ein Benutzer eingibt, musst du immer damit rechnen, dass der 
fehlerhaft ist!
Kriegst du den von einer Schnittstelle von einem anderen Programm 
zugespielt, reicht es die Maximallänge zu testen. Aber selbst dann 
sollte man im Hinterkopf behalten, dass die zur Verfügung stehenden 
char-Arrays nicht überlaufen werden.

(Deshalb ist die Lösung mit umkopieren nicht unbedingt die Methode der 
Wahl. Man muss viel Aufwand treiben um Fehlbedienung auszuschliessen)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.