aus char array zwei float Zahlen auslesen

Gast #1326398
Hallo zusammen,

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

4
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?
Michael schrieb:
> Hallo zusammen,
>
> ich habe wieder ein C/C++ Prgrammierproblem.
>
>
1
> char sResult[254];
2
> //fill sResult
3
> 
4
> printf("sResult = %s\n",sResult);
5
> 
6
>
>
> 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?
1
double Zahl1, Zahl2;
2

3
sscanf( sResult, "1T%lf\n2T%lf", &Zahl1, &Zahl2 );
Gast
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
Gast
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
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 );
Gast
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.
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.
echte regular expressions gehen nicht mit scanf(), aber
so etwas ähnliches:
1
  char sResult[] = "1TPTPPTPPTPTPTPT3.14159265354\n2PPPPTTT2.718281828";
2
  double    Zahl1, Zahl2;
3
  int nOk;
4

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

7
  if( nOk>=1 )
8
  {
9
    printf( "Zahl1 = %f\n", Zahl1 );
10
  }
11

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

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

Eine eigene Frage? Dieser Thread ist über 17 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.