mikrocontroller.net

Forum: Compiler & IDEs String aneinander reihen


Autor: TobyTetzi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

eine kleine Frage:

Ich möchte mehrere einzelne Strings aneinander hängen.

DisplayRAM = "Drehzahl:     " " U/min             " "Spannung:     " 
"Volt             " ;

Das geht auch so weit ganz gut.

Nur wie kann ich jetzt dieses erzeugen?

volatile unsigned int Zahl = 0;
volatile unsigned char string[5];
...

itoa( Zahl, string, 10);

DisplayRAM = "Drehzahl:     " string " U/min             " "Spannung: 
" string "Volt             " ;

Ich möchte also zum String die Werte der Zahl einfügen.

Gruß Toby

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sprintf()/snprintf(), oder die Teile einzeln mit strcat()/strncat()
zusammenfügen.

In jedem Falle musst du einen Zielpuffer bereitstellen, der genügend
Platz hat.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Deine aneinandergehängten Strings sind nicht wirklich aneinandergehängte 
Strings, sondern eine einzige große Stringkonstante.
Um das Zusammenfügen kümmert sich bereits der Preprocessor.

Um sich verändernde Werte an Strings anzuhängen, muss eine andere 
Vorgehensweise verwendet werden.

Einerseits benötigst Du einen ausreichend großen Puffer, der das 
Endergebnis aufnehmen soll, andererseits musst Du geeignete Funktionen 
zur Stringverarbeitung verwenden.
char buf[100];  // muss ausreichend groß sein!
char string[6]; // muss für Ausgabe von unsigned int reichen 


itoa(Zahl1, string, 10);

buf[0] = '\0';

strcat(buf, "Drehzahl: ");
strcat(buf, string);
strcat(buf,  " U/min  ");
strcat(buf,  " Spannung:  ");

itoa(Zahl2, string, 10);
strcat(buf, string);

strcat(buf, "Volt             ");

(die Formatierung der Leerzeichen etc. solltest Du Dir nochmal näher 
ansehen).

Bei Aufruf von itoa mit einem unsigned Int muss der übergebene Puffer 
übrigens Platz für sechs und nicht nur für fünf Zeichen bieten - ein 
unsigned int selbst kann eine fünfstellige Zahl sein, und die 
stringterminierende Null muss auch noch Platz finden.

Wenn ausreichend Programmspeicher zur Verfügung steht, lässt sich 
natürlich auch ein printf-Derivat einsetzen, was den Vorteil der auf 
definierbare Feldbreiten formatierten Ausgabe der numerischen Werte 
hätte.

Autor: Tobias Tetzlaff (tobytetzi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

müsste es dann so aussehen?

strcat("Drehzahl:     ", &string, &" U/min             ", &"Spannung:
", &string, &"Volt             ");

sprintf()/snprintf() möchte ich nicht nutzen, da ich dafür schon keinen 
Platz mehr im Programm habe.

Gruß Toby

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein, strcat hat exakt zwei Argumente. Den Adressoperator solltest Du 
übrigens auch weglassen.

Du musst also strcat für jedes anzuhängendes Stringfragment erneut 
aufrufen - wobei es Dir unbenommen bleibt, Stringkonstanten automatisch 
vom Preprocessor zusammenfassen zu lassen (U/min und Spannung).

Sofern Du einen AVR mit seiner praktischen Harvard-Architektur 
verwendest, solltest Du auch daran denken, daß Stringkonstanten im RAM 
abgelegt werden. Du solltest also darauf achten, diese via PROGMEM zu 
deklarieren und zu nutzen, dafür sollte dann ein strcat_P existieren:
char buf[100];  // muss ausreichend groß sein!
char string[6]; // muss für Ausgabe von unsigned int reichen 


itoa(Zahl1, string, 10);
buf[0] = '\0';

strcat_(buf, PSTR("Drehzahl: "));
strcat(buf, string);
strcat_P(buf,  PSTR(" U/min  "));
strcat_P(buf,  PSTR(" Spannung:  "));

itoa(Zahl2, string, 10);
strcat(buf, string);

strcat_P(buf, PSTR("Volt             "));

Für Deine zur Laufzeit erzeugten Strings musst Du natürlich das 
"normale" strcat verwenden.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
's ist übrigens der Compiler, der die Konstanten zusammenfasst, nicht
der Präprozessor.

Autor: Tobias Tetzlaff (tobytetzi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

danke für die schnelle Antwort.

ich nutze einen ATmega8, bzw dem ATmega168.

Ich brauche also nur die Strings für die dynamischen Werte im Ram legen,
die Konstanten (Drehzahl :) z.B. im Flasch, richtig?

Gruß Toby

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Den Zielstring musst du auch im RAM anlegen, d. h. du brauchst
irgendwo irgendwie genügend Platz dafür.

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Brauchst du den String eigentlich sicher an einem Stück?
Bei RS232 oder LCD-Ausgabe isses normalerweise möglich die Teilstrings 
einzeln nacheinander auszugeben.

also
  uart_print_P(PSTR("Drehzahl: "));
  uart_print_int(drehzahl);
  uart_print_P(PSTR("  U/min "));
 usw.

/Ernst

Autor: TobyTetzi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich brauche den String, um ihn auf einem LED Array anzuzeigen.

Eine Frage noch, in welcher Lib ist die Funktion "strcat" mit drin?

Ich bekomme noch den Fehler:

..../main.c:521: undefined reference to `strcat_'


Gruß Toby

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Eine Frage noch, in welcher Lib ist die Funktion "strcat" mit drin?

In der libc.a, die automatisch mit gelinkt wird.

> ..../main.c:521: undefined reference to `strcat_'

Die Funktion heißt auch entweder strcat() oder strcat_P(), aber
nicht strcat_().

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
http://www.mikrocontroller.net/articles/FAQ#Wie_fu...

Und der Kauf, das Durcharbeiten (zumindest der ersten paar Kapitel)
eines durchaus handelsüblichen Buches über C ist dringend ans
Herz gelegt.

Autor: TobyTetzi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Jörg,

habe es schon gesehen, da fehlte ein P.

Es geht jetzt wunderbar!

Eine letzte Sache noch:

Ich habe es jetzt so geschrieben:


volatile uint8_t *DisplayRAM = "Drehzahl: 0000 U/min 
Spannung: 0,00 Volt             ";
volatile unsigned int Zahl1 = 0;
volatile unsigned int Zahl2 = 0;
char buf[64];  // (habe max.64 Zeichen)
char string[6]; // muss für Ausgabe von unsigned int reichen

itoa(Zahl1, string, 10);
  buf[0] = '\0';

  strcat_P(buf, PSTR("Drehzahl: "));
  strcat(buf, string);
  strcat_P(buf,  PSTR(" U/min           "));
  strcat_P(buf,  PSTR("Spannung: "));

  itoa(Zahl2, string, 10);
  strcat(buf, string);

  strcat_P(buf, PSTR(" Volt              "));

  DisplayRAM = buf;

Angezeigt wird nun:

"Drehzahl: XXXX U/min           Spannung: XXX Volt              "

wie bekomme ich nun noch hier:             ^ ein Komma dazwischen?

"Drehzahl: XXXX U/min           Spannung: X,XX Volt              "

Da muß ich doch diese Funktion :
itoa(Zahl2, string, 10);
strcat(buf, string);
zerlegen, nach den ersten Ziffern ein "," schreiben, und dann die 
letzten Ziffern, richtig?

Gruß Toby

Autor: TobyTetzi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Karl Heinz,

ich habe schon ein C Buch (C für Mikrocontroller, von Franzis), 
allerdings ist es nicht so toll, da mir eigentlich immer die Beispiele 
genau zu meinem Problem fehlen.

Wenn ich die Beispiele hier lese, verstehe ich es eigentlich recht 
schnell.
Ich nutze ja meistens auch die Suchfunktion, bevor ich etwas spezielles 
frage. ;-)

Trotzdem danke.

Gruß Toby

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
TobyTetzi wrote:

> volatile uint8_t *DisplayRAM = "Drehzahl: 0000 U/min
> Spannung: 0,00 Volt             ";

Das volatile ist hier sehr wahrscheinlich überflüssig (und könnte dir
umständlichen Code erzeugen).  Der Datentyp darstellbarer Zeichen
sollte immer als "char" deklariert werden.

> volatile unsigned int Zahl1 = 0;
> volatile unsigned int Zahl2 = 0;

Stellt sich ebenfalls die Frage, wofür das volatile hier gut ist.

> Angezeigt wird nun:
>
> "Drehzahl: XXXX U/min           Spannung: XXX Volt              "
>
> wie bekomme ich nun noch hier:             ^ ein Komma dazwischen?
#include <stdlib.h>

...
  div_t d;

  d = div(Zahl2, 10);
  itoa(d.quot, string, 10);
  strcat(buf, string);
  strcat_P(buf, PSTR(","));
  itoa(d.rem, string, 10);
  strcat(buf, string);
  strcat_P(buf, PSTR(" Volt              "));

...

Zwar benutzt div() vorzeichenbehaftete Integerzahlen, während deine
Werte unsigned sind, aber itoa() benutzt ebenfalls int.  Wenn du also
Werte größer als 32767 hast, musst du das sowieso anders angehen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
TobyTetzi wrote:

> "Drehzahl: XXXX U/min           Spannung: XXX Volt              "
>
> wie bekomme ich nun noch hier:             ^ ein Komma dazwischen?
>
> "Drehzahl: XXXX U/min           Spannung: X,XX Volt              "
>
> Da muß ich doch diese Funktion :
> itoa(Zahl2, string, 10);
> strcat(buf, string);
> zerlegen, nach den ersten Ziffern ein "," schreiben, und dann die
> letzten Ziffern, richtig?

Das ist eine Möglichkeit, das ',' im Nachhinein in den String
einzuschmuggeln, ja.

Eine andere Möglichkeit:
Wieviel ergibt 523 / 10?  Richtig, das macht 5
Und was ergibt 523 % 10?  Genau, das macht 23

Wenn du also zuerst die 5 ausgibst, dann ein Komma und dann
die 23, steht auf deinem Display: 5,23

(Die führenden Nullen bei der Modulo Division nicht vergessen:
  507 % 10  macht 7!  D.h. bei der Ausgabe muss zuerst 5, dann
  ein Komma, dann eine 0 und dann erst die 7 ausgegeben werden)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
TobyTetzi wrote:
> Hallo Karl Heinz,
>
> ich habe schon ein C Buch (C für Mikrocontroller, von Franzis),
> allerdings ist es nicht so toll, da mir eigentlich immer die Beispiele
> genau zu meinem Problem fehlen.

Die wirst du auch in keinem Buch finden.
Programmieren lebt davon, dass man Bausteine kombinieren kann.
Bausteine können sein:
  Arithmetische Anweisungen
     kein µC kann aus einer Zeitdifferenz eine Frequenz berechnen.
     Aber es gibt die Operation 'Division'. Und wenn man jetzt
     noch weiss, dass
              f = 1 / t
     dann hat man das Problem durch Kombination von 2 'Bausteinen'
     gelöst

  Algorithmen
     Für viele Problemstellungen gibt es Standardverfahren.
     Ein gutes Buch führt einen auf spielerische Art und Weise
     in die wichtigsten und häufigsten Algorithmen ein, indem
     sie entweder besprochen oder aber als Idee skizziert und
     als Übungsaufgabe gestellt werden. Drum ist das Durcharbeiten
     von Übungsaufgaben in einem Programmierbuch auch so wichtig.

  Standardbibliotheken
     Einige (meist einfache) Algorithmen sind von so fundamentaler
     Bedeutung, dass mit dem Programmiersystem auch entsprechende
     vorgefertigte Funktionen mitgeliefert werden. Die sollte man
     kennen und mit ihnen (im Rahmen von Übungsaufgaben) auch mal
     gearbeitet haben, damit man sich an sie erinnert wenn man
     sie braucht.

Dreh und Angelpunt ist aber immer wieder eines:
Programmieren lernt man nur durch Programmieren. Ein Buch einfach
nur durchzulesen ist vergeudete Zeit. Man muss das, was man gelesen
hat auch sofort in einem Programm umsetzen, eventuell etwas abwandeln
um zu sehen, was man sonst noch mit der präsentierten Idee machen
kann. Nur so lernt man und merkt sich auch, welche Funktionen es
gibt, wie sie eingesetzt werden und welche Ideen dahinter stecken.
Dann hat man seine Bausteine im Kopf parat und kann sie abrufen
wenn man sie braucht. Das Buch braucht man dann nur noch, um Details
die man sich nicht gemerkt hat, nachschlagen zu können. Was aber nicht
heist, dass solche Detail-Nachschlagbücher (auch solche gibt es)
für den Anfang empfehlenswert sind. Ganz im Gegenteil.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger wrote:
> Eine andere Möglichkeit:
> Wieviel ergibt 523 / 10?  Richtig, das macht 5
> Und was ergibt 523 % 10?  Genau, das macht 23
Eher "/100" bzw. "%100", gell?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johannes M. wrote:
> Karl heinz Buchegger wrote:
>> Eine andere Möglichkeit:
>> Wieviel ergibt 523 / 10?  Richtig, das macht 5
>> Und was ergibt 523 % 10?  Genau, das macht 23
> Eher "/100" bzw. "%100", gell?

<Geräusch, das entsteht, wenn die Stirn auf der Tischplatte
aufschlägt>

Danke.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger wrote:
> <Geräusch, das entsteht, wenn die Stirn auf der Tischplatte
> aufschlägt>
Na, kein Grund zur Selbstverstümmelung;-) War nur, um sicherzugehen, 
dass kein unbedarfter Anfänger tatsächlich glaubt, 523 / 10 ist 5... 
Kannste ja oben ändern und meine beiden letzten Postings löschen...

Gruß

johnny.m

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> War nur, um sicherzugehen, dass kein unbedarfter Anfänger tatsächlich
> glaubt, 523 / 10 ist 5...

Ein Anfänger in Grundschulmathematik? ;-)

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf Magnus wrote:
>> War nur, um sicherzugehen, dass kein unbedarfter Anfänger tatsächlich
>> glaubt, 523 / 10 ist 5...
>
> Ein Anfänger in Grundschulmathematik? ;-)
Naja, hier muss man mit allem rechnen...;-)

Autor: Tobias Tetzlaff (tobytetzi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habs nun!

Jetzt gehts so, wie ich will, das ich auch veränderliche Werte anzeigen
kann.

Danke an alle, die mir mal mehr, mal weniger
mit Rat und Tat zur Seite standen!

Hier das Ergebnis:
Ein ca. 6MB großes Video.

http://www.tobytetzi.de/NightVision/NV2.0Rev7.1.mpg

Gruß Toby

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.