Forum: Compiler & IDEs fprintf %s Formatzeichen oder doch nur char Pointerfehler im 2D-Array?


von D a v i d K. (oekel) Benutzerseite


Lesenswert?

Hi,

ich experimentiere gerade mit einem kleinen LCD(HD44780) und muss 
feststellen, dass ich mich schon wieder in Pointerarithmetik verstricke, 
oder einfach nicht richtig verstehe, was "fprintf" intern macht.

Ich gebe Mal kurz das Bsp. und sage euch dann was ich erwarte bzw. nicht 
erwarte:
1
const char menue[][16]= {"IP-Adresse:     ", "MIDI-IN-THROU   ", "DMX-UNIVERSE 1  ", "DMX-UNIVERSE 2  ", "DMX-UNIVERSE 3  ", "DMX-UNIVERSE 4  "};
2
const char blend_left[] = "<<--<<--";
3
const char blend_right[] = "-->>-->>";
4
5
fprintf(&lcd_stdout, "%s%s%s",menue[m_item],blend_right, menue[m_item+1]);

Ich erwarte eine Ausgabe wie "IP-Adresse:     -->>-->>MIDI-IN-THROU   "
Bekomme aber einen Mischmasch aus allen Feldern.

Meine Vermutung ist, dass fprintf die Einträge ALLE konkateniert und 
dann aufs Display schreibt. Dieses hat aber nur 2x40 Zeichen und fängt 
dann warscheinlich wieder vorne an zu überschreiben, so dass ich den 
Mist sehe.

Da ich eh alle Leerzeichen reinschupsen muss, habe ich von einem 
Pointerarray a la char *menue[] Abstand genommen.

Könnt *ihr* mir *einen* Schubs *in* die *richtige* Richtung 
*geben?* (und nebenbei sagen, wie man ganze Sätze hier fett bekommt ;)


Ich dachte ich mache mir das Leben einfacher, indem ich nen Wrapper 
nutze:
1
static inline int lcd_putchar(char c, FILE* stream)
2
{
3
  lcd_sendchar(c);
4
}
 aber nun stehe ich da mit dem Halbwissen über fprintf und diese 
Formatzeichen wie %s.

Grüße Oekel

von Michael F. (startrekmichi)


Lesenswert?

Das Problem liegt nicht im fprintf, sondern eher daran, dass die Strings 
gar nicht terminiert sind, weil du keinen Platz für die terminierende 
'\0' gelassen hast.
1
const char menue[][17]= ...
An sonsten springt mir gerade nichts ins Auge...

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

Michael Frangenberg schrieb:
> Das Problem liegt nicht im fprintf, sondern eher daran, dass die Strings
> gar nicht terminiert sind, weil du keinen Platz für die terminierende
> '\0' gelassen hast.
>
1
const char menue[][17]= ...
> An sonsten springt mir gerade nichts ins Auge...

Und genau das wars dann auch schon. Perfekt danke!

Falls mir noch Jemand erklären könnte, warum sich dieser Effekt 
einstellt, wenn ich das Zeichen nicht mit einplane, wäre ich noch einen 
Tick schlauer.
Aber fürs erste bin ich wieder happy!

Grüße Oekel

von Markus M. (mark_m)


Lesenswert?

Das Thema mit den C-Strings wird hier im Forum einmal die Woche 
durchgekaut. Verwende bitte die Suchfunktion mit "C-String" und lies dir 
den Artikel durch: 
http://www.mikrocontroller.net/articles/String-Verarbeitung_in_C

Grüsse

von DirkB (Gast)


Lesenswert?

D a v i d K. schrieb:
> Falls mir noch Jemand erklären könnte, warum sich dieser Effekt
> einstellt, wenn ich das Zeichen nicht mit einplane, wäre ich noch einen
> Tick schlauer.

Das sind absolute Grundlagen für die Stringverarbeitung in C.

Es ist so vereinbart, das Strings in C mit einer '\0' terminirt werden.
Daran wird das Ende erkannt.

Wenn du ein
1
fprintf(&lcd_stdout, "%20s%s%s",menue[m_item],blend_right, menue[m_item+1]);
machst, brauchst du in deinen Texten die Leerzeichen am Ende auch nicht 
mehr.

von DirkB (Gast)


Lesenswert?

Ich korrigiere mich
1
fprintf(&lcd_stdout, "%-16.16s%s%s",menue[m_item],blend_right, menue[m_item+1]);
Es sollen ja 16 Zeichen sein, linksbündig und maximal 16 Zeichen.

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

Markus M. schrieb:
> Das Thema mit den C-Strings wird hier im Forum einmal die Woche
> durchgekaut. Verwende bitte die Suchfunktion mit "C-String" und lies dir
> den Artikel durch:
> http://www.mikrocontroller.net/articles/String-Verarbeitung_in_C
>
> Grüsse

Du hast natürlich Recht. Nachdem klar war, dass mein Fehler dort lag, 
hätte ich mich erneut ORDENTLICH auf die Suche machen müssen. Zumal die 
Artikel hier wirklich allererste Sahne sind. Sorry, der zweite Post war 
voreilig und faul...

DirkB schrieb:
>
1
fprintf(&lcd_stdout, "%-16.16s%s%s",menue[m_item],blend_right,
2
> menue[m_item+1]);

Danke, eben DAMIT kenne ich mich gar nicht aus, werde mich nun aber 
einlesen.

Grüße Oekel

von Wusel D. (stefanfrings_de)


Lesenswert?

Wenn ein String nicht mit \0 terminiert wird, dann endet er nicht. 
Irgendwo weiter hinten im Speicher wird zufällig ein Null-Byte stehen. 
Der String, den printf dann ausgibt wird genau bis dort gehen. Da Du 
drei Strings ausgibst, wiederholt sich der Fehler drei mal.

printf kann ohne das \0 Zeichen nicht wissen, wo der String endet. Den 
als Parameter wird nicht der ganze String übergeben, sondern ein Pointer 
auf das erste Zeichen. Es wird keine Längen-Angab eübergeben. Ob das 
Array als char[16] oder char[100] deklariert ist, kann printf nicht 
wissen.

Das gilt für alle String Funktionen.

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.