strtok Problem

#3327393
Lesenswert?

Hallo,

ich möchte eine zeichenkette getrennt von "," aufteilen,
dafür mache ich folgendes:
1
typedef struct MD{
2
         char all[40];
3
         char *Name1;
4
         char *Name2;
5
         char Number;
6
    }DESCRIPTION;
7

8
struct Tree {
9
    DESCRIPTION MD;              ///< Module Description
10
} Tree;
11

12

13
char *buffer;
14
buffer=0;
15

16

17
Tree.MD.Name1 = strtok(Tree.MD.all, ",");
18
Tree.MD.Name2 = strtok(NULL, ",");
19
buffer = strtok(NULL, ",");
20
Tree.MD.Channel=*buffer;

Tree.MD.all wird eingelesen. Kann zb "BLA,BLA123,3" sein....
Ich möchte dass in Tree.MD.Channel jetzt der dritte abschnitt nach den 
komma steht. da steht aber irgendwie immer was anderes drin. Wenn ich 
Name1 und Name2 printe steht da aber das richtige drin.... Auch wenn ich 
Channel ohne buffer auslese und ausgebe steht da das richtige drin..
Ich möchte aber den Wert von Channel haben.

Grüße
Gast #3327408
Lesenswert?

Du musst den saveptr noch mitgeben:

man strtok
1
           for (j = 1, str1 = argv[1]; ; j++, str1 = NULL) {
2
               token = strtok_r(str1, argv[2], &saveptr1);
3
               if (token == N[LL)
4
                   break;
5
               printf("%d: %s\n", j, token);
6

7
               for (str2 = token; ; str2 = NULL) {
8
                   subtoken = strtok_r(str2, argv[3], &saveptr2);
9
                   if (subtoken == NULL)
10
                       break;
11
                   printf(" --> %s\n", subtoken);
12
               }
13
           }

Grüsse,
René
Gast #3327452
Lesenswert?

In Deinem Fall müsste das demnach so aussehen (einfach so getippt uns 
ungetestet):
1
typedef struct MD{
2
         char all[40];
3
         char *Name1;
4
         char *Name2;
5
         char Number;
6
    }DESCRIPTION;
7

8
struct Tree {
9
    DESCRIPTION MD;              ///< Module Description
10
} Tree;
11

12

13
char *buffer;
14
buffer=0;
15

16
char* saveptr;
17

18
Tree.MD.Name1 = strtok(Tree.MD.all, ",");
19
Tree.MD.Name2 = strtok(NULL, ",", &saveptr);
20
buffer = strtok(NULL, ",", &saveptr);
21
Tree.MD.Channel=*buffer;

Grüsse,
René
Gast #3327453
Lesenswert?

Martin Rox schrieb:
> und wieso strtok_r statt strtok? ich meine strtok funktioniert ja, ich
> glaube nur dass irgendein pointer anstatt dem gewünschten inhalt
> ausgegeben wird.

Das war nur das Beispiel aus der man page. Du kannst natürlich strtok 
nehmen und brauchst nicht strtok_r.

Grüsse,
René
Gast #3327491
Lesenswert?

hmm...

da gehts:
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <stdint.h>
4
#include <string.h>
5
#include <math.h>
6

7

8

9
int main (int argc, char *argv[])
10
{
11
  char* saveptr;
12
  char* tok;
13
  char val[127];
14

15
  strcpy (val,  "12,34,56,78");
16

17

18
  tok = strtok_r(val, ",", &saveptr);
19
  fprintf (stdout, "Tok: %s\n", tok);
20

21
  tok = strtok_r(NULL, ",", &saveptr);
22
  fprintf (stdout, "Tok: %s\n", tok);
23

24
  return (0);
25
}


:~/gcctest> gcc -o tmp2 tmp2.c
:~/gcctest> ./tmp2
Tok: 12
Tok: 34

Grüsse,
René
Gast #3327492
Lesenswert?

Um es klarzustellen. Den saveptr gibt es nur bei strtok_r. strtok 
benötigt ihn nicht.

Martin Rox schrieb:
> Ich möchte dass in Tree.MD.Channel

Es gibt in Tree.MD kein Member mit Namen "Channel". Es wäre sinnvoll, 
den Code zu posten, den du tatsächlich probiert hast.


Martin Rox schrieb:
> token = strtok_r(Tree.MD.all, ",",&saveptr1);
>
>  error: assignment makes pointer from integer without a cast

Entweder hast du den Header vergessen, oder der Compiler ist in einen 
Modus geschaltet, in dem er strtok_r nicht kennt (z.B. C89 oder C99).
Gast #3327507
Lesenswert?

Poste mal den ganzen Code. Du hast da bei der Zuweisung einen Fehler 
(struct definition).

Rolf Magnus schrieb:
> Um es klarzustellen. Den saveptr gibt es nur bei strtok_r. strtok
> benötigt ihn nicht.

Das ist korrekt, dann muss man das Handling selber machen und jeweils 
den letzten Pointer als erster Parameter mitgeben.

Grüsse,
René
Gast #3327513
Lesenswert?

Dann eben mit strtok (nicht schön programmiert, nur um aufzuzeigen wie):
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <stdint.h>
4
#include <string.h>
5
#include <math.h>
6

7

8

9
int main (int argc, char *argv[])
10
{
11
  char* saveptr;
12
  char* tok;
13
  char val[127];
14

15
  strcpy (val,  "12,34,56,78");
16

17

18
  tok = strtok(val, ",");
19
  fprintf (stdout, "Tok: %s\n", tok);
20

21
  tok = strtok(tok+strlen(tok)+1, ",");
22
  fprintf (stdout, "Tok: %s\n", tok);
23

24
  // etc.....
25

26
  return (0);
27
}

Grüsse,
René
Gast #3327543
Lesenswert?

Rene H. schrieb:
> Rolf Magnus schrieb:
>> Um es klarzustellen. Den saveptr gibt es nur bei strtok_r. strtok
>> benötigt ihn nicht.
>
> Das ist korrekt, dann muss man das Handling selber machen und jeweils
> den letzten Pointer als erster Parameter mitgeben.

Nein. Das ist im Prinzip genau das, was man bei strtok_r macht. Bei 
strtok übergibt man einfach NULL. Den letzten Pointer merkt sich die 
Funktion intern, weshalb sie nicht reentrant ist. Dafür steht dann auch 
das _r bei strtok_r.
#3327550
Lesenswert?

huhu, jaaa das mit dem strtok geht bei mir auch. aber der trick ist ja, 
dass ich aus dem string die einzelnen wörter in variablen speicher will. 
und da speichert der irgendwie nichts gutes rein.
Beispiel:

String -> "Bla1,Bla2,123"

jetzt will ich dass 123 in meiner variablen "Nummer" steht...
wenn ich aber

 tok = strtok(val, ",");
Nummer=*tok;

mache, steht in nummer etwas anderes.... Also genauer ist der code am 
anfang den ich gepostet habe... Der fehler scheint bei der zuweisung zu 
entstehen, kann es sein dass hier:
Nummer=*tok;

nicht der inhalt ab dem komma, sondern nur der zeiger übergeben wird?
Gast #3327814
Lesenswert?

Martin Rox schrieb:
> seltsam, eigentlich ist nummer auch ein char. die sind eigentlich alle
> char :D aber mit atoi klappt es mit der nummer. wenn text drin steht
> dann klappt es nicht mit
>
> Nummer=*tok;

Was willst du denn nun drin speichern? Ein char kannst du verwenden, um 
genau ein Zeichen zu speichern, oder um eine Zahl im Bereich bis 127 (je 
nach CPU, aber 127 ist der sichere Wert) zu speichern.
Wenndu also Nunmmer=*tok schreibst, speicherst du das erste Zeichen von 
tok in Nummer. Wenn du atoi benutzt, wird das, was in tok steht, 
umgewandelt in eine Zahl, und die wird in Nummer gespeichert. Du kannst 
halt nicht beides haben.
Gast #3328043
Lesenswert?

Hi Martin,

ich habe den Eindruck, das nicht strtok Dein Problem war/ist. Kann es 
sein, dass Du ein Durcheinander machst mit Zeichenketten und Zahlen?

Falls ich Dich damit unterfordere, einfach ignrorieren.

ein
1
    char a;

stellt ein ASCII Zeichen dar und kann den numerischen Wert von -127 bis 
+127 annehmen. Im Speicher ist das ein Byte üblicherweise.

1
   char string[128];
2

3
   strcpy (string, "Meine Zeichenkette");

ist ein Zeiger auf eine Zeichenkette, also eine Anreihung von char's. Im 
Speicher braucht sie 128 Byte, benutzt davon werden aber lediglich  19 
Byte (inkl. der abschliessenden Null-Terminierung).

Wenn Du nun die Zuweisung machst:
1
    char aChar = *string;

steht in aChar ein M. Oder als Zahlenwert: 0x4d. Du dereferenzierst 
lediglich den char*, somit das erste Zeichen.


Wie willst Du Deine Tokens weiter verabeiten? Mit welchem Datentyp?
Du hast die Wahl Deine Tokens als String oder Wert zu verarbeiten:
1
    char    zahlenWert;
2
    uint8_t einByte;
3

4
    char tokenA[16];
5
    char tokenB[16];
6

7
    char* strZahl;
8

9
    strcpy (tokenA, "abc");
10
    strcpy (tokenB, "123");
11

12
    zahlenWert = *tokenA; // ergibt ASCII 0x61 oder 'a' als Zeichen
13
    zahlenWert = atoi(tokenA); // falsch, weil in Token A steht abc
14

15
    einByte = atoi(tokenB); // ergibt einByte = 123 als Zahl
16
    zahlenWert = *tokenB; // ergibt ASCII 0x31 oder '1' als Zeichen

Vielleicht hilft das etwas.

Grüsse,
René
Gast #3328148
Lesenswert?

Das Problem wird die Unwissenheit über den Unterschied zwischen Ziffer 
und Zahl oder konkret zwischen 3 und '3' und "3"

Bzw. das eine Zeichenkette nicht durch eine einfache Zuweisung zu einem 
Zahlenwert führt sondern erst mit Hilfe einer Funktion gewandelt werden 
muss.

Das ist halt C und keine Typenlose Scriptsprache.
#3328483
Lesenswert?

oah jetzt hab ichs hinbekommen.

Also erstmal ist es so, dass dieser strtok befehl irgendwie meinen 
strink zerhackt. Also habe ich den string vorher in eine neue variable 
kopiert, und die größen den chars definiert:
1
typedef struct MD{
2
         char all[40];
3
         char Name1[10];
4
         char Name2[20];
5
    }MD;
6

7
char all[40],*buffer;
8
strcpy(all,Tree.MD.all); //hier mache ich eine kopie um den string zu schützen

dann fange ich an:
1
buffer = strtok((char*)all, ",");
2
strcpy(Tree.MD.Name1,buffer);    //in meine variable speichern

und dann gehts weiter mit den nächsten teilen:
1
buffer = strtok(NULL, ",");
2
strcpy(Tree.MD.Name2,buffer);

und so weiter. dann habe ich den text in meinen variablen.
Spitze, danke für die hilfe.
Gast #3328484
Lesenswert?

Rene H. schrieb:
> ein
>     char a;
>
> stellt ein ASCII Zeichen dar und kann den numerischen Wert von -127 bis
> +127 annehmen.

Ich weiß nicht, wie es beim C32 ist, aber prinzipiell sollte man char 
höchstens für den Bereich 0 bis 127, oder besser noch, einfach gar nicht 
für das Speichern von Zahlen verwenden. Es ist dem Compiler überlassen, 
ob char mit oder ohne Vorzeichen ist. Übrigens: Wenn es ein Vorzeichen 
hat, ist der Bereich meistens eher -128 bis 127.

> Im Speicher ist das ein Byte üblicherweise.

Es ist immer ein Byte, denn genau so ist in C das Byte definiert - als 
die Speichermenge, die ein char belegt.
#3328963
Lesenswert?

Martin Rox schrieb:
> Also erstmal ist es so, dass dieser strtok befehl irgendwie meinen
> strink zerhackt.

Das ist das erwartete Verhalten von strtok(), steht auch in jeder Doku 
dazu drin.

Ansonsten würden die gelieferten Zeiger auf die einzelnen Token ja nicht 
auf jeweils nullterminierte Strings zeigen - die dafür notwendige 
Terminierung der einzelnen Token muß von strtok() in den String 
geschrieben werden anstelle des gefundenen Trennzeichens.
Gast #3329466
Lesenswert?

Rolf Magnus schrieb:
>> Im Speicher ist das ein Byte üblicherweise.
>
> Es ist immer ein Byte, denn genau so ist in C das Byte definiert - als
> die Speichermenge, die ein char belegt.

Ok, ich kannte die Definition nicht, resp. war mir unsicher, deshalb 
meine vorsichtige Aussage. Vorstellen hätte ich mir können, dass es 
irgendeinen Compiler gibt der per default oder Option w_char macht o.ä.
Ich meine, dass das hier auch schon Thema war.

Grüsse,
René

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