Forum: Compiler & IDEs sscanf mit Komma "," als Trennzeichen


von Hans (Gast)


Lesenswert?

Hallo,

ich möchte mit sscanf eine Zeichenkette splitten, wenn ich bei 
leerzeichen splitte funktioniert das auch schon:


char strData[20]="";
char strTest[20]="";
sscanf(strCmdPC,"%s %s",&strData, &strTest);

wenn ich allerdings das Leerzeichen durch ein komma ersetze, wird nicht 
mehr gesplittet?!

sscanf(strCmdPC,"%s,%s",&strData, &strTest);
oder
sscanf(strCmdPC,"%s/%s",&strData, &strTest);

funktioniert beispliesweise nicht!

Woran kann das liegen?


Grüße,


Hans

von yalu (Gast)


Lesenswert?

Für sscanf ist ein String eine zusammenhängede Folge von
Nicht-Whitespace-Zeichen, unabhängig davon, was im Formatstring danach
folgt. Deswegen wird auch das ',' und das '/' dem %s zugeordnet.

In deinem Fall ist wahrscheinlich die strtok-Funktion die bessere
Alternative.

von Timmo H. (masterfx)


Lesenswert?

yalu hats ja schon gesagt. Was mich aber wundert ist, dass dein Compiler 
nicht meckert.
Du machst ja das hier:
1
sscanf(strCmdPC,"%s %s",&strData, &strTest);
Du gibst sscanf &strData, aber strData ist ja schon ein Pointer. Enweder 
machst du das
1
sscanf(strCmdPC,"%s %s",strData, strTest);
oder das:
1
sscanf(strCmdPC,"%s %s",&strData[0], &strTest[0]);

Ach wahrscheinlich machst du nicht "-Wall". Man könnte sich ansonsten 
auch ne explode-Funktion ala PHP programmieren. Wenn du nur eine 
Trennstelle hast gehts auch so:
1
int main() {
2
char strCmdPC[] = "So ein Mist,was soll der Dreck";
3
char strData[20],strTest[20];
4
char *dat = strData, *test = strTest, *cmd = strCmdPC;
5
6
    while(*cmd != ',')
7
        *dat++ = *cmd++;
8
    *dat = '\0';
9
    while(*cmd++)
10
        *test++ = *cmd;
11
    *test = '\0';
12
13
printf("strData: %s\nstrTest: %s", strData,strTest );
14
}
Ist aber in der Ausführung ziemlich unsicher.

von Timmo H. (masterfx)


Lesenswert?

Ahh oder du machst sowas:
1
int main() {
2
    char strCmdPC[] = "So ein Mist,was soll der Dreck";
3
    char strTMP[100];
4
    char *ptr = strTMP;
5
    char *strData, *strTest;
6
    
7
    strcpy(strTMP,strCmdPC);
8
    
9
    while(*ptr++ != ',');
10
    *(ptr-1) = '\0';
11
    
12
    strData = strTMP;
13
    strTest = ptr;
14
    
15
printf("strData: %s\nstrTest: %s", strData,strTest );
16
}
Hach Pointer sind doch feine Sache :-)

von Karl H. (kbuchegg)


Lesenswert?

Timmo H. wrote:
> Ahh oder du machst sowas:
>
1
> ...
2
> 
3
>     while(*ptr++ != ',');
4
>     *(ptr-1) = '\0';
5
> ...
6
> }
7
>

Da kannst du dann aber auch gleich zum strtok greifen.
Der überprüft dann wenigstens auch noch, ob im String
das gesuchte Zeichen (bei strtok können das dann auch
gleich mehrere gleichzeitig sein) überhaupt enthalten
ist, bzw. behandelt den Fall, dass das Suchzeichen gleich
als erstes auftaucht richtig :-)

von Timmo H. (masterfx)


Lesenswert?

Wohl wahr, hab ja gesagt, dass es nicht gerade sicher ist. Aber wenn man 
nen uC hat ist es nicht immer machbar die ganzen Libraries einzubinden 
und da greife ich halt gerne auf solche Minimalfunktionen zurück.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Timmo H. wrote:

> Was mich aber wundert ist, dass dein Compiler
> nicht meckert.
...
> Du gibst sscanf &strData, aber strData ist ja schon ein Pointer.

Nein, ist es nicht.  Es ist der Name eines Arrays.  Zwar ist es
absolut überflüssig, von einem solchen die Adresse mit dem
Adressoperator zu bilden (da das bloße Nennen des Namens bereits
die Adresse bildet), aber zulässig ist es und absolut kein Grund
für eine Warnung.

von Timmo H. (masterfx)


Lesenswert?

Dann compilier das mal mit "-Wall" Dann kommt nämlich:
>> test3.c:7: warning: char format, different type arg (arg 3)
>> test3.c:7: warning: char format, different type arg (arg 4)
UND strData ist zwar der Name des Arrays, aber der Name ist gleichzeitig 
der Zeiger auf das erste element (strData[0]). Darum ist &strData[0] 
auch das gleiche wie strData.

von yalu (Gast)


Lesenswert?

Also mal langsam Schritt für Schritt:

1. strData ist ein char-Array mit 20 Elementen.

2. strData wird an eine Funktion als Zeiger auf ein char, nämlich auf
   das erste Element des Arrays, übergeben. Es ist und bleibt aber
   trotzdem ein Array.

3. &strData ist ein Zeiger auf ein char-Array mit 20 Elementen. Ein
   Zeiger auf ein char-Array ist etwas anderes als ein Zeiger auf ein
   char.

sscanf erwartet für das %s-Format einen Zeiger auf char.

Deswegen ist es richtig, einfach strData zu übergeben, da nach (2)
nicht das Array, sondern ein Zeiger auf das erste Element, das ein
char ist, übergeben wird.

Es ist unsauber, &strData zu übergeben, da es sich dabei nach (3)
nicht um einen Zeiger auf char handelt. Numerisch gesehen ist &strData
aber gleich dem Zeiger auf das erste Element, deswegen wird das
Programm dennoch funktionieren. Diese Unsauberkeit wird vom Compiler
aber mit einer entsprechenden Warnung angeprangert.

von Timmo H. (masterfx)


Lesenswert?

Wie auch immer, ich versuche immer alle warnings rauszuhauen.

von yalu (Gast)


Lesenswert?

> Wie auch immer, ich versuche immer alle warnings rauszuhauen.

Dieser Meinung bin ich auch. Eine Warnung ist durch sauberere
Formulierung eines Programmkonstrukts meist in weniger als einer
Minute beseitigt. Einen Fehler zu lokalisieren, der durch die
Beachtung der Warnungen vielleicht nicht passiert wäre, kann sehr viel
mehr Zeit in Anspruch nehmen.

Deswegen ist auch bei mir -Wall immer aktiv, meist auch noch -pedantic
oder -std=c99, weil ich mich gerne Standards beuge.

von Rolf Magnus (Gast)


Lesenswert?

@Timmo H. (masterfx):

> UND strData ist zwar der Name des Arrays, aber der Name ist
> gleichzeitig der Zeiger auf das erste element (strData[0]).

Ist es nicht. Es wird aber bei der Übergabe (und in den meisten, aber 
nicht allen, anderen Situationen) in einen Zeiger auf das erste Element 
konvertiert.

@yalu:

> Deswegen ist auch bei mir -Wall immer aktiv, meist auch noch -pedantic
> oder -std=c99, weil ich mich gerne Standards beuge.

Bei mir ist es eigentlich immer mindestens -ansi -pedantic -Wall 
-Wextra, bzw. evtl auch -std=c99, oder wenn ich mal GNU-Erweiterungen 
will, -std=gnu99. Und nein, -Wall schaltet nicht alle Warnungen ein.

Zu deinem Posting davor: Alle Aussagen dort sind richtig.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.