mikrocontroller.net

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


Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
yalu hats ja schon gesagt. Was mich aber wundert ist, dass dein Compiler 
nicht meckert.
Du machst ja das hier:
sscanf(strCmdPC,"%s %s",&strData, &strTest);
Du gibst sscanf &strData, aber strData ist ja schon ein Pointer. Enweder 
machst du das
sscanf(strCmdPC,"%s %s",strData, strTest);
oder das:
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:
int main() {
char strCmdPC[] = "So ein Mist,was soll der Dreck";
char strData[20],strTest[20];
char *dat = strData, *test = strTest, *cmd = strCmdPC;

    while(*cmd != ',')
        *dat++ = *cmd++;
    *dat = '\0';
    while(*cmd++)
        *test++ = *cmd;
    *test = '\0';

printf("strData: %s\nstrTest: %s", strData,strTest );
}
Ist aber in der Ausführung ziemlich unsicher.

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ahh oder du machst sowas:
int main() {
    char strCmdPC[] = "So ein Mist,was soll der Dreck";
    char strTMP[100];
    char *ptr = strTMP;
    char *strData, *strTest;
    
    strcpy(strTMP,strCmdPC);
    
    while(*ptr++ != ',');
    *(ptr-1) = '\0';
    
    strData = strTMP;
    strTest = ptr;
    
printf("strData: %s\nstrTest: %s", strData,strTest );
}
Hach Pointer sind doch feine Sache :-)

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

Bewertung
0 lesenswert
nicht lesenswert
Timmo H. wrote:
> Ahh oder du machst sowas:
>
> ...
> 
>     while(*ptr++ != ',');
>     *(ptr-1) = '\0';
> ...
> }
> 

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 :-)

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie auch immer, ich versuche immer alle warnings rauszuhauen.

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

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.