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


von Michael (Gast)


Lesenswert?

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?

von Karl H. (kbuchegg)


Lesenswert?

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

von Michael (Gast)


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

von Michael (Gast)


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

von Karl H. (kbuchegg)


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

von Michael (Gast)


Lesenswert?

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

Jetzt klappt es

Vieeelen Dank!!!
Super!

von Karl H. (kbuchegg)


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.

von Michael (Gast)


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.

von Karl H. (kbuchegg)


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.

von Klaus W. (mfgkw)


Lesenswert?

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!

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.