Forum: Compiler & IDEs printf für andere Funktionen


von Patrick B. (p51d)


Lesenswert?

Hallo miteinander

Ich habe einmal eine kleine Frage, ob es möglich ist, die 
Printf-Funktion auch für andere C-Funktionen zu nützen?

Damit man bequem zum Beispiel ein LCD ansteuern könnte, oder ein 
Ringbuffer für eine Kommunikation "bedienen"...

Ich dachte, dass ich schon mal so etwas gesehen hätte:
1
void lcd_putc(char c){
2
//
3
}
4
printf(lcd_putc,"Hallo Welt: %d\n",datum);

Gibt es so etwas schon oder wie müsste das aussehen?

Besten Dank für die Hilfe
MFG
Patrick

von Karl H. (kbuchegg)


Lesenswert?

Patrick B. schrieb:
> Hallo miteinander
>
> Ich habe einmal eine kleine Frage, ob es möglich ist, die
> Printf-Funktion auch für andere C-Funktionen zu nützen?

Möglich (beim gcc) schon.
Aber dazu muss man eine Ausgabefunktion für Einzelzeichen unter das 
printf in das I/O System für den Ausgabe-Stream einschmuggeln

> Damit man bequem zum Beispiel ein LCD ansteuern könnte, oder ein
> Ringbuffer für eine Kommunikation "bedienen"...
>
> Ich dachte, dass ich schon mal so etwas gesehen hätte:
>
1
> void lcd_putc(char c){
2
> //
3
> }
4
> printf(lcd_putc,"Hallo Welt: %d\n",datum);
5
>

So höchst wahrscheinlich nicht.

Wenn da eine zusätzliches Argument beim 'printf' war, dann war das 
höchst wahrscheinlich
1
  char buffer[30];
2
  sprintf( buffer, "Hallo Welt: %d\n", datum );
3
  lcd_puts( buffer );

von Oliver (Gast)


Lesenswert?

Patrick B. schrieb:
> Ich habe einmal eine kleine Frage, ob es möglich ist, die
> Printf-Funktion auch für andere C-Funktionen zu nützen?

printf ist eine Funktion aus der Standard-library, und alles 
wissenswerte dazu steht in der der Doku zu der von dir benutzten 
Version.

Falls du zufällg AVR's progrtammierst, und das auch noch zufällig mit 
avr-gcc und der avr-libc machst, dann geht das. Wie, steht in der 
avr-libc-Doku zu printf.

Oliver

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

sprintf() schreibt aber nur in einen Puffer, der dem aufrufenden 
Programm gehört. Mittels fprintf() kann man jedoch in verschiedene 
Ausgabedateien bzw. -datenströme schreiben. Ursprünglich bei unixoiden 
Betriebssystemen, aber mittlerweile durchaus auch allgemein 
gebräuchlich, sind die Dateideskriptoren 0-2 für Standardausgabe, 
Standardeingabe und Standardfehlerkanal (stdout, stdin, stderr) 
reserviert. "Echte" Dateideskriptoren besitzen dann höhere Kennungen.

Um eine Ausgabeumlenkung zu realisieren, sollte man in den Quelltext der 
C-Bibliothek schauen. Dann kann man schnell entscheiden, ob man z.B. 
einen eigenen Handler für stderr realisiert oder zusätzliche Geräte 
"erfindet".

Ggf. befinden sich in den Beschreibungen zu 
Compiler/Standardbibliotheken auch schon entsprechende Hinweise oder 
Anleitungen, wie eine Anpassung der Ein-/Ausgabekanäle erfolgen kann.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Patrick B. schrieb:
> Hallo miteinander
>
> Ich habe einmal eine kleine Frage, ob es möglich ist, die
> Printf-Funktion auch für andere C-Funktionen zu nützen?
>
> Damit man bequem zum Beispiel ein LCD ansteuern könnte, oder ein
> Ringbuffer für eine Kommunikation "bedienen"...
>
> Ich dachte, dass ich schon mal so etwas gesehen hätte:
>
1
> void lcd_putc(char c){
2
> //
3
> }
4
> printf(lcd_putc,"Hallo Welt: %d\n",datum);
5
>
>
> Gibt es so etwas schon oder wie müsste das aussehen?

Falls du die avr-libc verwenden willst/kannst kann man sich nen eigenens 
stdout bauen so wie beschrieben in

http://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html#stdio_without_malloc

Damit kommt printf allerdings nur mit dem Standardumfang. Funktionalität 
wie wie zB Cursor-Positionierung, Display löschen etc. sind da nur 
holprig unterzubringen.

von Patrick B. (p51d)


Lesenswert?

Die Neu-Definition von der Stream-Funktion beim AVR GCC kenne ich, aber 
ich habe das noch nie für eine andere Funktion gesehen.

Bei einem CCS-Compiler für PIC's in der Schule habe ich diese 
möglichkeit gesehen, und auch schon angewendet.

Momentan versuche ich mich gerade an einem HI-Tech Compiler, aber leider 
habe ich da nicht viel in der Doku (immerhin >450 Seiten) gesehen.
in den Header-Files habe ich nur volgendes gefunden:
1
extern char *  gets(char *);
2
extern int  puts(const char *);
3
extern int  scanf(const char *, ...);
4
extern int  sscanf(const char *, const char *, ...);
5
extern int   vprintf(const char *, va_list);
6
extern int  vsprintf(char *, const char *, va_list);
7
extern int  vscanf(const char *, va_list ap);
8
extern int  vsscanf(const char *, const char *, va_list);
9
10
#pragma  printf_check(printf) const
11
#pragma  printf_check(sprintf) const
12
extern int sprintf(char *, const char *, ...);
13
extern int printf(const char *, ...);

Soweit ich weiss, ist der CCS nicht immer Regelkonform.

Könnte man so eine Funktion auch selber schreiben?

MFG
Patrick

von Karl H. (kbuchegg)


Lesenswert?

Patrick B. schrieb:

> Momentan versuche ich mich gerade an einem HI-Tech Compiler, aber leider
> habe ich da nicht viel in der Doku (immerhin >450 Seiten) gesehen.
> in den Header-Files habe ich nur volgendes gefunden:
>
1
> extern char *  gets(char *);
2
> extern int  puts(const char *);
3
> extern int  scanf(const char *, ...);
4
> extern int  sscanf(const char *, const char *, ...);
5
> extern int   vprintf(const char *, va_list);
6
> extern int  vsprintf(char *, const char *, va_list);
7
> extern int  vscanf(const char *, va_list ap);
8
> extern int  vsscanf(const char *, const char *, va_list);
9
> 
10
> #pragma  printf_check(printf) const
11
> #pragma  printf_check(sprintf) const
12
> extern int sprintf(char *, const char *, ...);
13
> extern int printf(const char *, ...);
14
>
>
> Soweit ich weiss, ist der CCS nicht immer Regelkonform.

Solche Sachen sind nie 'regelkonform', vor allen Dingen deshalb nicht, 
weil der C-Standard nicht fordert, das du das machen kannst.


> Könnte man so eine Funktion auch selber schreiben?

Man könnte.
Siehe zb hier
Beitrag "AVR32 printf umleiten stdout"

Allerdings hat man dann einen fix dimensionierten Buffer drinnen, den 
man da eigentlich nicht haben möchte.

Meiner Meinung nach, wird die Möglichkeit printf direkt auf einem 
'Gerät' benutzen zu können, auf µC überschätzt. Das bringt viel weniger 
als man sich erwartet oder auf einem Desktop System zur Verfügung hat. 
Hauptsächlich deshalb, weil man meistens sowieso Spezialfunktionalität 
benötigt, um zb den Cursor irgendwo hin zu schicken.

Und den Rest kann man auch mit einer guten String-Ausgabefunktion und 
Funktionen zur Konvertierung von Zahlen in Strings gut und vor allen 
Dingen resourcenschonend erledigen. Muss man nicht auf Speicher und 
Laufzeit achten, und hat man eine gute Verwendung für die 
Formatiermöglichkeiten, die einem die ...printf() Familie bietet, ist 
auch sprintf eine nicht allzuschlechte Möglichkeit.

von Patrick B. (p51d)


Lesenswert?

Ich habe das jetzt über sprintf gelöst:
1
void lcd_write(char *i_string){
2
3
  while(*i_string!=0){
4
    lcd_putc(*(i_string++));
5
  }
6
  __delay_ms(1);
7
}
8
9
sprintf(lcd_string_buf,"\fConnected with PC\nWaiting for command\n/data");
10
lcd_write(lcd_string_buf);

Funktioniert eigentlich soweit so gut.

MFG
Patrick

von Karl H. (kbuchegg)


Lesenswert?

Patrick B. schrieb:

> sprintf(lcd_string_buf,"\fConnected with PC\nWaiting for
> command\n/data");
> lcd_write(lcd_string_buf);

Wozu brauchst du ganz konkret bei dieser einen Ausgabe den sprintf?
1
  lcd_write( "\fConnected with PC\n"
2
             "Waiting for command\n"
3
             "/data" );

lcd_write gibt einen String aus.
Du hast einen String.

von Patrick B. (p51d)


Lesenswert?

Wenn ich direkt einen String ind die Funktion lcd_write geschrieben 
habe, bekam ich eine Fehlermeldung wegen eines ungültigen Pointer-Typs.
über eine Array habe ich dann keine Fehlermeldung mehr bekommen.

von Karl H. (kbuchegg)


Lesenswert?

Patrick B. schrieb:
> Wenn ich direkt einen String ind die Funktion lcd_write geschrieben
> habe, bekam ich eine Fehlermeldung wegen eines ungültigen Pointer-Typs.
> über eine Array habe ich dann keine Fehlermeldung mehr bekommen.

Ich vergass. Du benutzt ja keinen gcc.
Höchst wahrscheinlich benutzt dein Compiler für konstante Texte einen 
anderen Speicherort und darum musst du den Umweg gehen.

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.