C & gcc & sscanf & longdouble als xx.xxxxxxxxE+yy

OP #4977526
Lesenswert?

Hallo,

ich bekomme von meinem Frequenzzähler via BUS folgenden String:

FA +0010.00001587E+06
Per strtok setze ich einen pointer auf die 1 und versuche dann die Zahl 
mit allen Stellen einzulesen.

->
long double strip_answer(char *answer, char *para) {
  char delimiter[] = " +";
  char *ptr;
  long double value;

  fprintf(stderr,"Answer %s", answer);
        ptr = strtok(answer, delimiter);
  if(! strcmp(ptr,para)) {
          fprintf(stderr,"Abschnitt gefunden: %s\n", ptr);
    ptr = strtok(NULL, delimiter);
    sscanf(ptr,"%LG",&value);
    fprintf(stderr,"Ausgabe %LG\n\r", value);
  }
  return value;
}

->
Answer FA +0010.00001520E+06
Abschnitt gefunden: FA
Ausgabe 10
->

Wo ist mein Denkfehler?

Gruß Andreas
#4977573
Lesenswert?

Andreas F. schrieb:
> Hallo,
>
> ich bekomme von meinem Frequenzzähler via BUS folgenden String:
>
> FA +0010.00001587E+06
> Per strtok setze ich einen pointer auf die 1 und versuche dann die Zahl
> mit allen Stellen einzulesen.

Du setzt ihn nicht auf die 1, sondern auf die erste 0, was aber nichts 
macht.
Das Problem ist, dass du an allen Leerzeichen und allen +-Zeichen eine 
Trennung machst, also bekommt strtok als String übergeben: 
"0010.00001587E", denn nach dem E steht ein +. Also bekommt es als 
Ergebnis 10.00001587 raus, da die Zehnerpotenz fehlt. Warum machst du 
überhaupt das + weg? Das stört doch gar nicht.
OP #4977966
Lesenswert?

@Rolf & Stefan
Jopp, danke

@Dirk & Rolf
long double zum testen, weil ich mir nicht sicher war, wo mein Fehler 
lag.


sscanf(answer, "FA%Lf", &value);
Jein,
Ja, funktioniert:
Nein. Weil ich die Routine modular halten will und bei den Antworten vom 
Bus schauen muss was im Header steht, (FA/FB/FC für die 3 Eingänge des 
Counters oder Pegel beim SA/Meßsender.

Gruß Andreas
#4978025
Lesenswert?

Na dann
1
char kanal;
2
sscanf(answer, "F%c%Lf", &kanal, &value);
In kanal steht dann 'A', 'B' oder 'C'.
Und wenn nicht, liegt ein Fehler vor.

Oder
1
char kanal[3];
2
sscanf(answer, "%2s%Lf", kanal, &value);
Dann halt mit "FA", "FB" oder "FC"

Es bleibt bei einem Einzeiler.
Unterschätze nicht die Macht von scanf
Gast #4978245
Lesenswert?

Dirk B. schrieb:
> Na dann
>
1
> char kanal;
2
> sscanf(answer, "F%c%Lf", &kanal, &value);
> In kanal steht dann 'A', 'B' oder 'C'.
> Und wenn nicht, liegt ein Fehler vor.
>
> Oder
>
1
> char kanal[3];
2
> sscanf(answer, "%2s%Lf", kanal, &value);
> Dann halt mit "FA", "FB" oder "FC"
>
> Es bleibt bei einem Einzeiler.
> Unterschätze nicht die Macht von scanf

Ja, weil es für den einen Fall funktioniert.

Nein, weil ich das als Standardroutine für alle GPIB read haben will.
Aufbau ist HH +DDDDDDDD.DDDD[cr\LF]

Wobei HH dann z.b 'DU', FA, AT sein kann, je nach Meßgerät und Funktion,

Die Funktion muss ich eh noch erweitern, weil die Antwort beim bei einem 
DDS Arbitrary Funktionsgenerator deutlich komplexer ist.


Gruß Andreas
#4978540
Lesenswert?

bazo schrieb:
>> char kanal[3];
>> sscanf(answer, "%2s%Lf", kanal, &value);> Dann halt mit "FA", "FB" oder "FC"
>>
>> Es bleibt bei einem Einzeiler.
>> Unterschätze nicht die Macht von scanf
>
> Ja, weil es für den einen Fall funktioniert.
>
> Nein, weil ich das als Standardroutine für alle GPIB read haben will.
> Aufbau ist HH +DDDDDDDD.DDDD[cr\LF]

Passt doch. In kanal steht dann das HH

Man kann den Formatstring auch noch anpassen, wenn es mehr als zwei H 
sind.
#4978561
Lesenswert?

Das Problem von strtok ist, dass es den String verändert (an die 
Position vom Delimiter wird ein '\0' geschrieben.

Und es ist nicht reentrant/threadsafe.
Wenn in einer der rufenden/parallelen Funktionen noch eine nicht 
abgeschlossenen strtok-Suche offen ist, geht das in die Hose.
Gast #4978788
Lesenswert?

Dirk B. schrieb:
> bazo schrieb:
>>> char kanal[3];
>>> sscanf(answer, "%2s%Lf", kanal, &value);> Dann halt mit "FA", "FB" oder "FC"
>>>
>>> Es bleibt bei einem Einzeiler.
>>> Unterschätze nicht die Macht von scanf
>>
>> Ja, weil es für den einen Fall funktioniert.
>>
>> Nein, weil ich das als Standardroutine für alle GPIB read haben will.
>> Aufbau ist HH +DDDDDDDD.DDDD[cr\LF]
>
> Passt doch. In kanal steht dann das HH
>
> Man kann den Formatstring auch noch anpassen, wenn es mehr als zwei H
> sind.

Auch wenn die Anzahl der Parameter und das Trennzeichen sich 
unterscheidet?
Mittels strtok kann ich solange die Antwort durchlaufen, bis ich alle 
Parameter habe.

Dirk B. schrieb:
> Das Problem von strtok ist, dass es den String verändert (an die
> Position vom Delimiter wird ein '\0' geschrieben.
>
> Und es ist nicht reentrant/threadsafe.
> Wenn in einer der rufenden/parallelen Funktionen noch eine nicht
> abgeschlossenen strtok-Suche offen ist, geht das in die Hose.

Das trifft hier nicht zu, es wird über die Funktion aus der libgpip oder 
direkt von /dev/usbtmc die Antwort gelesen und dann die Antwort zerlegt, 
das ganze in einem Programm. Und selbst wenn ich aus dem Auslesen 
jemalss ein eigenen Thread mache, Schnittstelle ist immer record.xyz. 
Der Stringinhalt ist danach eh obsolet.

Überschrieben, weil ich den Wert zyklisch auslese.
Überschrieben, weil ich den nächsten Query absetze.
Oder die Routine wird dann irgendwann durch den User wieder aufgerufen, 
daa wir das eh neu vom Bus eingelesen.

Gruß Andreas
PS:
Gibt es in C eine Funktion, die analog zu int main(int argc, char 
*argv[] funktioniert? Aufrufen mit einem String und in der Funktion 
bekommt man die einzelnen Argumente aufgedröselt geliefert?
#4978858
Lesenswert?

bazo schrieb:
> PS:
> Gibt es in C eine Funktion, die analog zu int main(int argc, char
> *argv[] funktioniert? Aufrufen mit einem String und in der Funktion
> bekommt man die einzelnen Argumente aufgedröselt geliefert?

Das macht nicht die Funktion sondern das Betriebssystem bzw. der 
Startupcode.

Möchtest du eine variable Anzahl Argumente benutzen?

Man kann das aber mit scanf und einer Schleife hinbekommen.
Gast #4979008
Lesenswert?

Dirk B. schrieb:
> bazo schrieb:
>> PS:
>> Gibt es in C eine Funktion, die analog zu int main(int argc, char
>> *argv[] funktioniert? Aufrufen mit einem String und in der Funktion
>> bekommt man die einzelnen Argumente aufgedröselt geliefert?
>
> Das macht nicht die Funktion sondern das Betriebssystem bzw. der
> Startupcode.
>
> Möchtest du eine variable Anzahl Argumente benutzen?
>
> Man kann das aber mit scanf und einer Schleife hinbekommen.

Ja, nur weiss ich nicht, ob ich immer die erwartete Anzahl an Parameter 
zurückbekomme und die Reihenfolge ob String oder numerisch ist völlig 
frei:

vom DDS Arbitrary Funktionsgenerator z.b.
BSWV WVTP, 
SINE,FRQ,100HZ,PERI,0.01S,AMP,2V,OFST,0V,HLEV,1V,LLEV,-1V,PHSE,0
Vom Zähler/den einem SA halt obiges HH DDDD.DDDDE0x
Den zweite SA/Bolometer habe ich noch nicht angeschaut

Als Trennzeichen habe ich je nach dem " ",";",",",:"
Der Grundaufbau ist immer gleich,
- Bedienoberfläche für die wichtigsten Einstellungen

- Capture des aktuellen Bildes
- Kurvenschreiber (Datenlogger)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren