Forum: Compiler & IDEs sscanf-Parameter durch Funktion hindurch geben


von Richard W. (richi)


Lesenswert?

Hallo

ich möchte mir eine Funktion machen, in der u.a sscanf vorkommt. Die 
Zeigerliste, die man normalerweise in sscanf einfügt,
z.B. sscanf(text,"%d%d%d...",&a,&b,&c)  => &a,&b,&c
soll genauso an meine Funktion übergeben werden, wobei diese Funktion 
dann genau diese Variablen an die sich der Funktion befindenden 
sscanf-Funktion übergibt.

Ich hoffe es ist euch klar geworden.

Wie baut man sowas auf?


Viele Grüße
Richi

von Sebastian C. (basti79)


Lesenswert?

Moin,

ich hab sowas mal für printf gemacht, eigentlich das gleiche und das 
solltest du dann dementsprechend anpassen können. Die magischen Worte 
zum Googlen sind hier "variable argument list".
1
extern void error_exit(const char *msg, ...) 
2
  __attribute__ ((format (printf, 1, 2)));
3
4
void error_exit(const char *msg, ...) {
5
  va_list va;
6
7
  va_start(va, msg);
8
  vfprintf(stderr, msg, va);
9
  va_end(va);
10
  exit(EXIT_FAILURE);
11
}

Das _attribute_ beim Prototyp brauchst du nicht unbedingt, aber 
dadurch kann der Compiler den Syntax der variablen Argumente prüfen; ist 
glaube ich auch gcc spezifisch.

Greets
  Basti.

von Richard W. (richi)


Lesenswert?

Vielen Dank.

Was genau bewirkt das mit dem _atributte_?
Das habe ich noch nicht so ganz begriffen.

Der Rest ist mir jetzt klar.

Viele Grüße
Richi

von Karl H. (kbuchegg)


Lesenswert?

Richard W. schrieb:
> Vielen Dank.
>
> Was genau bewirkt das mit dem _atributte_?


Das teilt dem gcc mit, wie das bei dieser Funktion mit den variadischen 
Argumenten (so heißt eine variable Argumentliste im Jargon) gedacht ist: 
Deine Funktion verhält sich so wie printf, d.h. ein String steuert die 
Auswertung der restlichen Argumente.

Das ermöglicht dem gcc etwas, was normalerweise nicht möglich ist:
Er prüft, ob deine %-Kürzel zur tatsächlichen restlichen Argumentliste 
passen. Dies deshalb, weil es ja für printf keinen herkömmlichen 
Protoypen der Funktion geben kann. Denn da steht ja nur:

void printf( const char*, ... )

das also beliebige andere Argumente kommen können. Und wenn du zb

  double j = 5.0;
  print( "%d", j );

machst, dann gibt das die tollsten Effekte. %d ist nun mal für int und 
nicht für double, d.h. das passt nicht zusammen. Nur mit Prüfung des 
Prototypen ist das nicht detektierbar. Also hat man dem gcc eine 
Erweiterung eingebaut, die den Compiler in die Lage versetzt, hier mal 
sein Prototypen-Prüfschema über Bord zu werfen und stattdessen mit dem 
String die restlichen Argumente auf Plausibilität abzuklopfen.

von Richard W. (richi)


Lesenswert?

Also wenn dann dein Fall auftreten würde, käme dann eine Fehler oder 
Warnmeldung beim kompilieren?

von Rolf Magnus (Gast)


Lesenswert?

Ja. Das hätte man übrigens auch im Handbuch von gcc nachlesen könne.

von Richard W. (richi)


Lesenswert?

OK, alles klar.

Vielen Dank!!!

Richi

von Richard W. (richi)


Lesenswert?

Hallo nochmal.

Wie kann ich denn noch Argumente von der Funktion her an sscanf anreihen 
lassen?


va_list  => &a,&b,&c  (übergebene Paramter variabler Anzahl)

Funktion fügt &d hinzu =>  &a,&b,&c,&d

==> sscanf(text,format,&a,&b,&c,&d)


Viele Grüße
Richi

von Klaus W. (mfgkw)


Lesenswert?

geht nicht.

Zumindest nicht ohne unportable Schweinereien.

von Rolf Magnus (Gast)


Lesenswert?

Richard W. schrieb:
> Wie kann ich denn noch Argumente von der Funktion her an sscanf anreihen
> lassen?

Auch das kann man im gcc-Handbuch nachlesen.

von Richard W. (richi)


Lesenswert?

Wo soll es denn stehen?
Ich finde es jedenfalls nicht.

Wenn mir jemand ein passendes Stichwort sagt, finde ich es ja 
vielleicht.

von Klaus W. (mfgkw)


Lesenswert?

variadic ist sicher kein schlechtes Stichwort (wobei ich nicht weiß,
ob die glibc für so einen Fall etwas Sinnvolles kennt).

Ich kann mir auch nicht recht vorstellen, daß es irgendwie
sinnvoll ist. Ohne den Formatstring zu verlängern, ist es doch
ziemlich witzlos, irgendwelche Argumente anzuhängen?

Wenn schon, dann auch vielleicht in der glibc zu suchen, statt
beim gcc.

von Karl H. (kbuchegg)


Lesenswert?

Ich würds auch lassen.
Solche variadischen Dinge arten ganz schnell in ein Nightmare aus, wenn 
man nicht aufpasst und sind fehleranfällig bis zum geht nicht mehr.

von Richard W. (richi)


Lesenswert?

Den Formatstring ändert meine Funktion schon, nur das hinten anhängen 
der Parameter für die Funktion funktioniert noch nicht.

Mit dem Stichwort variadic habe ich auch nur Lösungen gefunden, die 
Argumenteliste an die Letzte Stelle zu positionieren, nicht aber die 
Lösung, danach noch Parameter anzuhängen.

Mitlerweile glaube ich aber auch, dass es wirklich zu einem "Nightmare" 
kommt, ich hätte nicht gedacht, dass es so kompliziert ist.

Viele Grüße
Richi

von Rolf Magnus (Gast)


Lesenswert?

Richard W. schrieb:
> Wo soll es denn stehen?

Oh, sorry. Ich hatte dein Posting mißverstanden, muß also alles 
zurücknehmen und mich den anderen anschließen. Es gibt meines Wissens 
keinen sinnvollen Weg, die Argumentliste nachträglich zu verändern.

von ichbins (Gast)


Lesenswert?

Ich versuche das gerade um mir für SDL eine TTF-Printf-Ausgabe zu 
basteln, allerdings wills nich so ganz.
1
int ttf_printf(const char *fontfile, int size, int x, int y, const char *format, ...) {
2
    va_list va;
3
    va_start(va, format);
4
    printf("%s %d %d %d: ",fontfile,size,x,y);
5
    printf(format, va);
6
    va_end(va);
7
    return 0;
8
}
Der Aufruf sieht so aus:
1
ttf_printf("fontbig.ttf", 12, 200, 400, "hello world %d\n", 40);

und das kommt dabei raus:
> fontbig.ttf 12 200 400: hello world -1075731612
Irgendwie kommt das "40" nicht durch und was angezeigt wird, scheint 
irgendwie ins leere zu greifen, kann mir dabei jemand helfen?

von Rolf Magnus (Gast)


Lesenswert?

Du kannst nicht einfach eine va_list als Argument an printf übergeben. 
Du mußt stattdessen vprintf benutzen.

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.