Anfängre string zerlgen

Gast #1649012
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.
#1649044
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.
#1649050
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.
#1649052
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
#1649053
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.
#1649056
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.
#1649070
Lesenswert?

Aber um mal etwas Leben in die Bude zu bekommen
1
#include <stdio.h>
2
#include <string.h>
3

4
int main(void)
5
{
6

7
  {
8
    // einfach einen Token nach dem anderen ausgeben.
9
    // Das benutzt man wenn man nicht alle token in einem Rutsch braucht
10
    char string[] = "command,arg1, arg2";
11
    char *token;
12
    token = strtok( string, ", " );   // zerlegt wird an , und Leerzeichen
13
    while( token != NULL )
14
    {
15
      printf( "%s\n", token );
16
      token = strtok( NULL, ", " );        /* weitere Token ermitteln */
17
    }
18
  }
19
  
20
  printf( "\n\n" );
21

22
  {
23
    // hier werden alle Token zwischengespeichert (Pointer in den Originalstring)
24
    // das braucht man, wenn zb eine Funktion aufgerufen wird, die alle
25
    // Token auf einmal braucht
26
    char string[] = "command,arg1, arg2";
27
    char *token;
28
    char* tokens[20];
29
    int   nrTokens = 0;
30
    int   i;
31
    
32
    token = strtok( string, ", " );   // zerlegt wird an , und Leerzeichen
33
    while( token != NULL )
34
    {
35
      tokens[nrTokens++] = token;
36
      token = strtok( NULL, ", " );        /* weitere Token ermitteln */
37
    }
38

39
    for( i = 0; i < nrTokens; i++ )
40
      printf( "%s\n", tokens[i] );
41
  }
42
  
43
  return 0;
44
}
#1649078
Lesenswert?

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

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

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

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

3
// Kommando aus empfangener SMS auslesen
4
char *ptr_nachricht;
5
char nachricht[161];  // strtok verändert string --> Kopie anlegen
6
SMS_CMD_LIST_T keyItem = {"",NULL};
7
strcpy(nachricht,sms_dec_data.nachricht);
8
//nachricht in Kleinbuchstaben umwandeln
9
ptr_nachricht = nachricht;  // Startadresse übergeben
10
while(*ptr_nachricht){
11
  if (*ptr_nachricht >= 'A' && *ptr_nachricht <= 'Z') {
12
    *ptr_nachricht = *ptr_nachricht - 'A' + 'a';
13
  }
14
  ptr_nachricht++;
15
}
16
// sortieren der Befehlsliste (Voraussetzung für bsearch)
17
char *tmp;
18
qsort(&sms_cmd_list, (sizeof(sms_cmd_list)/sizeof(SMS_CMD_LIST_T)), sizeof(SMS_CMD_LIST_T), (int(*)(const void*,const void*))strcmp);
19
ptr_nachricht = strtok_r(nachricht,SMS_DELIMITER,&tmp);  // ersten Befehl extrahieren
20
while (ptr_nachricht!=NULL){
21
// Befehle entsprechend Liste ausführen
22
  strcpy(keyItem.cmd,ptr_nachricht);  // gefundenes Kommando übergeben
23
  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);
24
  if (spItem != NULL) { spItem->fp(0); }
25
  ptr_nachricht = strtok_r(NULL,SMS_DELIMITER,&tmp);  // neues Kommando suchen (falls mehrerer vorhanden sind)
26
}

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)
#1650213
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren