Forum: Compiler & IDEs String aneinander reihen


von TobyTetzi (Gast)


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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

von Rufus Τ. F. (rufus) Benutzerseite


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.
1
char buf[100];  // muss ausreichend groß sein!
2
char string[6]; // muss für Ausgabe von unsigned int reichen 
3
4
5
itoa(Zahl1, string, 10);
6
7
buf[0] = '\0';
8
9
strcat(buf, "Drehzahl: ");
10
strcat(buf, string);
11
strcat(buf,  " U/min  ");
12
strcat(buf,  " Spannung:  ");
13
14
itoa(Zahl2, string, 10);
15
strcat(buf, string);
16
17
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.

von Tobias T. (tobytetzi)


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

von Rufus Τ. F. (rufus) Benutzerseite


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:
1
char buf[100];  // muss ausreichend groß sein!
2
char string[6]; // muss für Ausgabe von unsigned int reichen 
3
4
5
itoa(Zahl1, string, 10);
6
buf[0] = '\0';
7
8
strcat_(buf, PSTR("Drehzahl: "));
9
strcat(buf, string);
10
strcat_P(buf,  PSTR(" U/min  "));
11
strcat_P(buf,  PSTR(" Spannung:  "));
12
13
itoa(Zahl2, string, 10);
14
strcat(buf, string);
15
16
strcat_P(buf, PSTR("Volt             "));

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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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

von Tobias T. (tobytetzi)


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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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

von Εrnst B. (ernst)


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

von TobyTetzi (Gast)


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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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_().

von Karl H. (kbuchegg)


Lesenswert?

http://www.mikrocontroller.net/articles/FAQ#Wie_funktioniert_String-Verarbeitung_in_C.3F

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

von TobyTetzi (Gast)


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

von TobyTetzi (Gast)


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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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?
1
#include <stdlib.h>
2
3
...
4
  div_t d;
5
6
  d = div(Zahl2, 10);
7
  itoa(d.quot, string, 10);
8
  strcat(buf, string);
9
  strcat_P(buf, PSTR(","));
10
  itoa(d.rem, string, 10);
11
  strcat(buf, string);
12
  strcat_P(buf, PSTR(" Volt              "));
13
14
...

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.

von Karl H. (kbuchegg)


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)

von Karl H. (kbuchegg)


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.

von Johannes M. (johnny-m)


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?

von Karl H. (kbuchegg)


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.

von Johannes M. (johnny-m)


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

von Rolf Magnus (Gast)


Lesenswert?

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

Ein Anfänger in Grundschulmathematik? ;-)

von Johannes M. (johnny-m)


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...;-)

von Tobias T. (tobytetzi)


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

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.