Forum: Compiler & IDEs Variable in string Funktion übergeben


von Simon T (Gast)


Lesenswert?

Hallo Leute,

seit einigen Wochen beschäftige ich mit dem Thema LCD am 
Mikrocontroller.
Nach einigen einsamen Stunden am Rechner ist es mir auch gelungen texte 
an dem LCD auszugeben.

Zum Problem: Um einen ganzen String an das LCD zu senden, habe ich 
mittels Pointer gearbeitet.
1
void lcd_text(unsigned char *zeile1,unsigned char *zeile2)
2
{
3
  lcd_line1();                    //cursor nach links in zeile 1
4
  while (*zeile1)                 //schleife solange zeichen vorhanden
5
  {
6
    lcd_schreiben(*zeile1++);   //ein zeichen weiter schreiben 
7
  }
8
  lcd_line2();                    //cursor nach links in zeile 2
9
  while (*zeile2)                 //schleife solange zeichen vorhanden
10
  {
11
    lcd_schreiben(*zeile2++);   //ein zeichen weiter schreiben
12
  }
13
  
14
}

Das funktioniert auch wie folgt:
1
void main(){
2
lcd_text("Vielen Dank!","Schon mal!");
3
}
Ich möchte allerdings jetzt z.B die Temperatur anzeigen lassen, wie 
folgt:
1
void main(){
2
3
char temp = 15;
4
5
lcd_text("Temperatur",temp);
6
}
wie muss ich temp schreiben bzw. umwandeln?

von Karl H. (kbuchegg)


Lesenswert?

Zualler erst mal hast du dir die Basisfunktion ungeschickt geschrieben.

Das du eine Funktion hast, die 2 Strings auf einmal ausgeben kann, ist 
gut. Aber du hast nicht gesehen, dass da 2 mal die noch primitivere 
Basisfunktion "gib 1 String aus" drinnen steckt.
1
void lcd_string( const char* str )
2
{
3
  while( *str )
4
    lcd_schreiben( *str++ );
5
}

damit schreibt sich dann dein lcd_text als
1
void lcd_text(unsigned char *zeile1,unsigned char *zeile2)
2
{
3
  lcd_line1();                    //cursor nach links in zeile 1
4
  lcd_string( zeile1 );
5
6
  lcd_line2();                    //cursor nach links in zeile 2
7
  lcd_string( zeile2 );
8
}

Noch hat sich nichts verändert.
Aber die Dinge ändern sich. Denn um
1
lcd_text("Temperatur",temp);
das hier zu tun, ist die Funktion lcd_text unbrauchbar. Die kann ja 2 
Strings ausgeben. Aber nicht einen String und einen int. Einen String 
könntest du (dank lcd_string) ausgeben, aber um den int auszugeben 
brauchst du eine weitere Hilfsfunktion, die genau das (und nicht mehr) 
kann: einen int ausgeben.

FAQ
(gleich der erste Punkt)

und der Rest ist wieder ein Kinderspiel. Du hast eine Funktion, die 
einen String ausgeben kann - du hast eine Funktion die einen int 
ausgeben kann - was also ist naheliegender, als mit diesen beiden 
Hilfsfunktionen (und den entsprechenden lcd_line Funktionen) eine 
weitere Funktion zu bauen
1
void lcd_wert( const char* label, int wert )
2
{
3
  lcd_line1();
4
  lcd_string( label );
5
6
  lcd_line2();
7
  lcd_int( wert );
8
}

und damit kannst du dann im Hauptprogramm das hier machen
1
...
2
   lcd_text( "Vielen Dank!", "Schon mal!" );
3
   lcd_wert( "Temperatur", temp );
4
...


Die Kunst besteht momentan auf dieser Ebene noch darin, sich selbst 
einen kleinen universell einsetzbaren Baukasten an Basisfunktionen zu 
machen, aus dem sich dann komplexere Sachen zusammensetzen lassen.
Deine 'Basisfunktion' war noch nicht primtiv genug, daher sind da keine 
Bausteine für andere Basisfunktionen abgefallen. Mit dem lcd_string und 
der noch von dir zu schreibenden lcd_int hat sich das geändert.

: Bearbeitet durch User
von lex (Gast)


Lesenswert?

Naja, lcd_text erwartet einen String (char *), also kannst du keinen 
char übergeben, und auch keinen int oder sonstwas.
(Ich würd übrigens das unsigned weglassen, hier gehts ja um Text)

Du musst also aus deinem "char temp" irgendwie einen String formen.
Ein Tipp: schau dir mal die Standard-Funktion itoa() an.
Zusätzlich musst du dir Speicher reservieren, den du dan an atoi() 
übergibst damit diese hineinschreiben kann.

von Mark B. (markbrandis)


Lesenswert?

Mönsch, das macht ja keinen Spaß hier wenn der buchegg schon nach 11 
Minuten die komplette Antwort gibt. ;-)

von Simon T (Gast)


Lesenswert?

Vielen dank erstmal für die schnelle und gute Antwort, buchegg. Das 
leuchtet ein!

Jetzt habe ich aber noch folgendes Problem:
1
int lcd_int(int wert)
2
{
3
int buffer[10];
4
itoa(wert,buffer,10);
5
return(buffer);
6
}

So sollte ja die lcd_int aussehen, allerdings kennt Ride7 trotz include 
von stdlib, die itoa nicht??

von Oliver (Gast)


Lesenswert?

Simon T schrieb:
> Jetzt habe ich aber noch folgendes Problem:

Bei dem Code hast du zwei Probleme ;)

Das andere wirst du erkennen, wenn dein Code mal compiliert, und dann 
das Programm abstürzt, oder zumindest nur Blödsinn anzeigt.

Oliver

von Rolf Magnus (Gast)


Lesenswert?

Oliver schrieb:
> Bei dem Code hast du zwei Probleme ;)

Drei...

Simon T schrieb:
> Jetzt habe ich aber noch folgendes Problem:
> int lcd_int(int wert)
> {
> int buffer[10];

Wenn du einen String willst, sollte das ein Array aus char sein, nicht 
int.

> itoa(wert,buffer,10);
> return(buffer);

Autsch! Du gibst hier einen Zeiger zurück auf einen Puffer, der bei 
Rückkehr auf die Funktion freigegeben wird und daher im Aufrufer 
tunlichst nicht zu verwenden ist.

> }
>
> So sollte ja die lcd_int aussehen, allerdings kennt Ride7 trotz include
> von stdlib, die itoa nicht??

Dann wird "Ride7" (was immer das sein mag) die nicht unterstützen. Es 
ist keine Standard-Funktion.

von Simon T (Gast)


Lesenswert?

Sorry bin seit 10 Uhr am programmieren, langsam gehts berg ab!
1
char lcd_int(int wert)
2
{
3
char buffer[10];
4
sprintf(buffer,"%d",wert);
5
return(buffer);
6
}

so Probleme beseitigt, bis auf eins. Wie soll ich den Wert zurück geben?

von Karl H. (kbuchegg)


Lesenswert?

Rolf Magnus schrieb:

> Dann wird "Ride7" (was immer das sein mag) die nicht unterstützen. Es
> ist keine Standard-Funktion.


Schon richtig, ist keine Standardfunktion.
Sie könnte auch _itoa heissen. Dann wäre sogar die Namensgebung ganz 
korrekt. Wenn auch das nicht, dann wird man wohl zum aussersten greifen 
müssen und die Ride7 Doku zur Rate ziehen. Oder man schreibt sie sich 
selber. Ist ja nicht schwer (und da dieses so ist, wundert es mich, dass 
es nichts gleichwertiges in Ride7 [was immer dieses Ride7 auch sein 
soll] gibt)

@Simon
> So sollte ja die lcd_int aussehen

Nein. Eigentlich nicht.
Sinn der Funktion lcd_int ist es, etwas auf das LCD auszugeben! In 
völliger Analogie zu den anderen lcd_.... Funktionen.
Deine Funktion gibt aber nichts aus! Scheinbar hast du den Link in die 
FAQ entweder nicht gesehen oder nicht gelesen.
1
void lcd_int(int wert)
2
{
3
  char buffer[10];
4
5
  itoa(wert, buffer, 10);
6
  lcd_string( buffer );
7
}
(bzw. dann eben die Funktion, die du als Ersatz für itoa hernimmst.)


in deinem Baukasten:
1
lcd_string     gibt einen String auf das LCD aus
2
lcd_int        gibt einen int auf das LCD aus
mit der besonderen Betonung auf 'gibt ... aus'. Und wenn diese 
Konvention in deinem Baukasten gilt, dann sollen die Funktionen dann 
auch genau das tun. Und zwar möglichst einheitlich, damit man sich das 
auch merken kann.

: Bearbeitet durch User
von Peter II (Gast)


Lesenswert?

Simon T schrieb:
> so Probleme beseitigt, bis auf eins. Wie soll ich den Wert zurück geben?

das geht nun mal nicht. Aus dem Grund gibt auch itoa keinen String 
zurück.

von lex (Gast)


Lesenswert?

Ok, sprintf ist natürlich die Holzhammermethode.
Nicht dass ich davon abraten würde, das musst du wissen ob du die 
Resourcen hast. Ich selbst benutz es mittlerweile auch, weils mir zu 
blöd ist jeweils 10 verschiedene Interfaces für Lcd und UART zu haben, 
je nachdem was ich ausgeben will.
Mit der printf-Familie hast du ein einziges Interface und kannst dem 
alles übergeben.


Aaaaaber: wenn du anscheinend vor hast, sprintf zu nutzen dann ist die 
Funktion lcd_int obsolet.
Wenn das printf-Zeugs dazugelinkt wird hast du nicht mehr das Problem, 
verschiedene Funktionen für verschiedene Datentypen schreiben zu müssen. 
Dann brauchst du keine lcd_text() oder lcd_wert() mehr.
Du kannst dir eine Funktion anlegen die alles ausgeben kann.

Aber der dritte Weg ist, eine itoa() selber zu schreiben. Das ist kein 
Hexenwerk und könnt dich weiterbringen.

von Simon T (Gast)


Lesenswert?

So vielen vielen Dank! Es läuft!
1
void lcd_int(int wert)                  //Funktion zum umwandeln von Int in String
2
{
3
char buffer[16];                        //String mit 16 Stellen
4
sprintf(buffer,"%d",wert);              // "drucken" des wertes vom Typ Int in die Variable "buffer"
5
lcd_string(buffer);
6
}

hatte nen leichtes Brett vorm Kopf :).

Jetzt ist Feierabend für heute!

Schönen Abend

von Peter II (Gast)


Lesenswert?

Simon T schrieb:

> void lcd_int(int wert)                  //Funktion zum umwandeln von Int in 
String

> Jetzt ist Feierabend für heute!


das ist wieder ein schönen Problem mit sinnlosen Kommentaren, jetzt 
passt der Kommentar nicht mehr zur Funktion

von Karl H. (kbuchegg)


Lesenswert?

Simon T schrieb:

Nicht das ich ein Problem damit habe, aber

> char buffer[16];                        //String mit 16 Stellen

erstens sind es nur 15 Stellen.
Aber. Wieso 15? Wie gross ist denn ein int auf deinem System?

Wenn der, was auf einem AVR üblich ist, 2 Bytes groß ist (also 16 Bit), 
dann hat der einen Wertebereich von -32768 bis 32767. Das sind als 
maximal 5 Stellen für die Ziffern und noch 1 Stelle für ein mögliches 
negatives Vorzeichen. Macht in Summe 6 benötigte Stellen, also ist ein 
Array der Länge 7 ausreichend.

Wie gesagt, es wird nicht viel ausmachen, da ein paar Bytes zuviel 
anzulegen und wenn man die Ausgabe etwas freier macht, dann schadet das 
auch nicht. Aber mit einem 16-Bit int ist es in DIESER Funktion 
technisch nicht möglich, mehr als 6 druckbare Zeichen zu erhalten.

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

> Wenn der, was auf einem AVR üblich ist,

Ah!
Merke gerade, dass an keiner Stelle im ganzen Thread von einem AVR die 
Rede ist.
Vergiss bitte das vorhergehende Posting.

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.