www.mikrocontroller.net

Forum: PC-Programmierung aus char array zwei float Zahlen auslesen


Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich habe wieder ein C/C++ Prgrammierproblem.
char sResult[254];
//fill sResult

printf("sResult = %s\n",sResult);


sResult enthält folgendes:
1TP0.0000\n2TP0.0000
Das "\n" ist ein Zeilenumbruch.

Bei dem füllen des Arrays ist immer ein 1TP gefolgt von einer Kommazahl. 
Danach ein Zeilenumbruch und 2TP gefolgt von einer Kommazahl. Die 
Formatierung ist auch immer gleich (siehe Bsp.)
Ich möchte nun die beiden Kommazahlen in unterschiedlichen Variablen 
speichern. Wie mache ich das?

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

Bewertung
0 lesenswert
nicht lesenswert
Michael schrieb:
> Hallo zusammen,
>
> ich habe wieder ein C/C++ Prgrammierproblem.
>
>
> char sResult[254];
> //fill sResult
> 
> printf("sResult = %s\n",sResult);
> 
> 
>
> sResult enthält folgendes:
> 1TP0.0000\n2TP0.0000
> Das "\n" ist ein Zeilenumbruch.
>
> Bei dem füllen des Arrays ist immer ein 1TP gefolgt von einer Kommazahl.
> Danach ein Zeilenumbruch und 2TP gefolgt von einer Kommazahl. Die
> Formatierung ist auch immer gleich (siehe Bsp.)
> Ich möchte nun die beiden Kommazahlen in unterschiedlichen Variablen
> speichern. Wie mache ich das?
double Zahl1, Zahl2;

sscanf( sResult, "1T%lf\n2T%lf", &Zahl1, &Zahl2 );

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für die schnelle Antwort.

Habe das gleich mal umgesetzt und erhalte jedoch "nur":

printf("Zahl1= %lf\n",Zahl1);
printf("Zahl2= %lf\n",Zahl2);

folgende Ausgabe:
Zahl1= 0.000000
Zahl2= 0.000000

Dies aber auch wenn z.B. nicht 0.0000 in dem char steht sondern der z.B. 
so aussieht:
1TP0.0000\n2TP0.0005

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Entschuldige,

ich hatte einen Fehler und hab nicht &Zahl1,&Zahl2, sondern nur 
Zahl1,Zahl2 in sscanf eingetragen.

Allerdings ist es trotzdem (noch) nicht richtig:
printf("sResult= %s\n",sResult);
Ausgabe:
sResult= 1TP-0.0005
2TP0.0000

sscanf( sResult, "1T%lf\n2T%lf", &Zahl1, &Zahl2 );
printf("Zahl1= %lf\n",Zahl1);
printf("Zahl2= %lf\n",Zahl2);

Ausgabe:
Zahl1= 0.000000
Zahl2= 
189036386038403088057117598843902933455662669321988840590337000865846180 
376463338129764928.000000

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

Bewertung
0 lesenswert
nicht lesenswert
Michael schrieb:

Mein Fehler.
Wenn in deinem String ein "TP" vorkommt, dann sollte man das dam sscanf 
auch richtig mitteilen :-)

> sscanf( sResult, "1T%lf\n2T%lf", &Zahl1, &Zahl2 );
  sscanf( sResult, "1TP%lf\n2TP%lf", &Zahl1, &Zahl2 );

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry,
wie dumm  von mir. Da hab ich gar nicht drauf geachtet.

Jetzt klappt es

Vieeelen Dank!!!
Super!

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

Bewertung
0 lesenswert
nicht lesenswert
Michael schrieb:
> Vieeelen Dank!!!
> Super!

Womit auch der Nachteil dieser Methode unmittelbar klar geworden ist. 
Wenn sich der String ein wenig (unbedeutend) ändert, dann bricht das 
alles zusammen.

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn das Programm, welches diesen String schickt korrekt programmiert 
ist (was ich hoffe), dann sollte dieser immer so aussehen und es sollten 
sich nur die beiden Zahlen ändern.

Ist es deutlich komplizierter auf variable Strings vorbereitet zu sein?
Deine Lösung ist einfacher als ich erwartet habe.

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

Bewertung
0 lesenswert
nicht lesenswert
Michael schrieb:
> Wenn das Programm, welches diesen String schickt korrekt programmiert
> ist (was ich hoffe), dann sollte dieser immer so aussehen und es sollten
> sich nur die beiden Zahlen ändern.

Das Problem, welches immer wieder mal auftritt:
Der andere Programmierer entscheidet, dass er das Protokoll leicht 
(natürlich kompatibel :-) ändert.

> Ist es deutlich komplizierter auf variable Strings vorbereitet zu sein?
> Deine Lösung ist einfacher als ich erwartet habe.

Man kann mit sscanf auch "regular Expressions" angeben. Aber damit kenne 
ich mich nicht aus.
Abgesehen davon: So kompliziert ist das auch wieder nicht, wenn man es 
händisch macht. Ob du das als 'deutlich' ansehen willst, hängt 
wahrscheinlich von dir ab. Aber mit einem 10-Zeiler wirst du nicht davon 
kommen, wenn man das wasserdicht machen will.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
echte regular expressions gehen nicht mit scanf(), aber
so etwas ähnliches:
  char sResult[] = "1TPTPPTPPTPTPTPT3.14159265354\n2PPPPTTT2.718281828";
  double    Zahl1, Zahl2;
  int nOk;

  nOk = sscanf( sResult, "1%*[A-Za-z]%lf 2%*[TP]%lf", &Zahl1, &Zahl2 );

  if( nOk>=1 )
  {
    printf( "Zahl1 = %f\n", Zahl1 );
  }

  if( nOk>=2 )
  {
    printf( "Zahl2 = %f\n", Zahl2 );
  }

In dem Formatstring steht die 1 für ein zu lesendes Zeichen '1' wie
gehabt.
%[A-Za-z] (ohne Stern) würde für alle Groß- und Kleinbuchstaben stehen,
also auch beliebige 'T' und 'P' in jeder Reihenfolge und alles, was
in dieser Muster packt, in ein char-Feld kopieren.

Mit einem Stern (also %*[A-Za-z]) dagegen unterbleibt das Kopieren,
die gelesenen Zeichen ('T' und 'P' z.B.) werden wegegeworfen.
%lf dann wie gehabt für eine double.
Das Leerzeichen passt ebenso als wenn ein \n stehen würde für
jedes white space, also auch \r, \t etc.
Die 2 passt auf ein Zeichen '2'.
%*[TP] liest alle Folgen aus 'T' und 'P' und wirft sie weg
(wegen des Sterns).


Und: (s)scanf liefert zurück, wieviele Umwandlungen erfolgreich
waren (wobei die mit * unterdrückten Umwandlungen nicht gezählt
werden, im besten Fall also 2).
Man sollte unbedingt diesen Rückgabewert mit den erwarteten
Umwandlungen vergleichen, um nicht mit blödsinnigen Werten
zu rechnen!

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.