Forum: Mikrocontroller und Digitale Elektronik MSP430 IAR: String1 in String2 Kopieren??


von XMEN (Gast)


Lesenswert?

hallo.
weisst jemand wie ich ein String1 in einen anderen String2 kopieren 
kann?

BSP:
String1 = "  Hallo Word " muss in String2 kopiert.

danke

von Bernhard (Gast)


Lesenswert?

Wie wärs mit?

#include <string.h>

und dann

strcopy (string2, string1);

von Christian R. (supachris)


Lesenswert?

Das wäre die brutal-Methode mit massenhaft Speicherplatz-verschwendung 
durch die dazu gelinkte Library.

Wieso nicht einfach:

while(*string1 != 0)
{
*string2 = *string1;
string1++;
string2++;
}

Dazu müssen allerdings die Strings als Pointer deklariert sein, was ja 
eh sinnvoll ist:

char *string1 = {"Blabla"};
char *string2 = {"blabla"};

wichtig ist, auch den 2. String schon mit irgendwelchen zeichen zu 
definieren, damit der Compiler weiß, wieviel Platz er reservieren muss.

von XMEN (Gast)


Lesenswert?

danke
es hat geklapt.

die erste Version ist einfacher und hat funktioniert. danke euch

von Bernhard (Gast)


Lesenswert?

Ähm,

der Compiler übersetzt doch eh alles in Maschinencode, oder?
Und die Library is doch nur für den Compiler?
Is dann nicht alles nur die Frage welchen Compiler du verwendest? Und 
wie gut der optimiert?

Korrigier mich wenn ich mich irre.

von XMEN (Gast)


Lesenswert?

wie kann ich dann bis zu einem bestimmten zeichen kopieren?? sagen wir 
bis zum nächsten leezeichen? und im String liegen 3 leezeichen.

danke

von Karl heinz B. (kbucheg)


Lesenswert?

> Dazu müssen allerdings die Strings als Pointer deklariert sein, was ja
> eh sinnvoll ist:
>
> char *string1 = {"Blabla"};
> char *string2 = {"blabla"};

Autsch.
genau so darfst du es auf keinen Fall machen.
Die Pointer zeigen auf konstante String Literale.
Die sind für dein Programm tabu und dürfen im Program
nicht verändert werden.

Wenn schon, dann zumindest

char *string1 = {"Blabla"};
char string2[] = {"blabla"};

Das ist ein kleiner Unterschied.

> Das wäre die brutal-Methode mit massenhaft Speicherplatz-verschwendung
> durch die dazu gelinkte Library.

Völliger Unsinn. Die str... Funktionen hast du sowieso mit,
weil sie in der C-Standardlibrary enthalten sind, die der
Compiler immer mit dazulinkt.
Und wenn dein Linker freundlich genug ist, alles was in der
Standardlibrary nicht gebraucht wird auch nicht mit ins EXE
zu übernehmen, so sind die Kosten für strcpy() auch nicht
höher als wenn du die Funktion selber schreibst. Im schlimmsten
Fall enthält dein EXE 2 strcpy(): Eines aus der Standard-Library
und eines das du selbst geschrieben hast. Also lass es.


von Bernhard (Gast)


Lesenswert?

Dann von Hand, denk ich.


unsigned char i=0;
//es sei denn dein String ist länger als 254 Zeichen + '\0

while (i<Stringlänge)
{
while( string1[i] !=' ' && string[i] !='\0')
{
string2[i]=string1[i];
i++;
}
}


Geht vermutlich auch eleganter, funktioniert aber erstmal.

von Karl heinz B. (kbucheg)


Lesenswert?

Bernhard wrote:
> Dann von Hand, denk ich.
>
>
> unsigned char i=0;
> //es sei denn dein String ist länger als 254 Zeichen + '\0
>
> while (i<Stringlänge)
> {
> while( string1[i] !=' ' && string[i] !='\0')
> {
> string2[i]=string1[i];
> i++;
> }
> }
>
>
> Geht vermutlich auch eleganter, funktioniert aber erstmal.

Allerdings.
Die Stringlänge brauchst du gar nicht.
In C ist ein String definiert als eine Zeichenfolge,
die mit einem '\0' Zeichen aufhört.

Obiges ist schon eine sehr spezielle Kopierfunktion,
die fischt dir alle Leerzeichen aus dem String heraus
(Was ist wenn da ein Tabulator drinn ist? :-)
Alle, nicht nur die Einleitenden. Bist du sicher das
du das haben möchtest?

Auch darfst du nicht vergessen im Zielstring auch das
letzte '\0' wieder reinzustellen.
1
void myCopy( const char* source, char* dest )
2
{
3
  while( *source) {
4
    if( *source != ' ' && *source != '\t' ) {
5
      *dest = *source;
6
      dest++;
7
    }
8
    source++;
9
  }
10
11
  *dest= '\0';
12
}

von Christian R. (supachris)


Lesenswert?

Also damit der GCC konstante Strings erzeugt, muss ich doch "const" vor 
die Deklaration schreiben. Ansonsten ist das ein Array am Ende, was im 
RAM liegt. Der Kompiler reserviert den Speicher und schreibt in dem Fall 
den Text rein, ans Ende hängt er eine Null. Kann man sich wunderbar im 
Debugger anschauen nachher. Wie das der IAR hält weiß ich nicht. Und der 
GCC linkt auch die StdLib nicht dazu, wenn ich das nicht explizit 
angebe.

Ich programmiere µCs nach Möglichkeit effizient, wozu brauch ich ne 
ganze Lib für so nen Pillepallekram? Schluckt nur wertvollen 
Programmspeicherplatz.
Die paar Pointer-Operationen sind doch schnell geschrieben.

von Karl heinz B. (kbucheg)


Lesenswert?

> Also damit der GCC konstante Strings erzeugt, muss ich doch "const" vor
> die Deklaration schreiben.

Ein String Literal, wie "Dies ist ein String" ist per C Definition
konstant. Dein Programm hat kein Recht da drin irgendwelche
Zeichen zu verändern.

von Karl heinz B. (kbucheg)


Lesenswert?

> Ansonsten ist das ein Array am Ende, was im
> RAM liegt.

Dann probier mal folgendes:
1
#include <avr/io.h>
2
3
char* Text1 = "Ein Text";
4
char* Text2 = "Ein Text";
5
6
int main()
7
{
8
  Text1[2] = 'b';
9
  Text2[3] = 'a';
10
11
}

Dann kompilierst du das mal mit -Os
und anschliessend machst du:
  * Du vergleichst mal die Pointerinhalte von Text1 und Text2
  * Du lääst dir mal *Text1 und *Text2 ausgeben

Es lohnt sich!



von Karl heinz B. (kbucheg)


Lesenswert?

> Und der
> GCC linkt auch die StdLib nicht dazu, wenn ich das nicht explizit
> angebe.

Ach. Wie gibst du denn explizit an, dass du die StdLib
mit dazugelinkt haben willst? Da bin ich jetzt aber
neugierig.

> Ich programmiere µCs nach Möglichkeit effizient, wozu brauch ich ne
> ganze Lib für so nen Pillepallekram?

Vielleicht deshalb, weil in der Standard Library das komplette
Runtime System von C enthalten ist? Das braucht nämlich
dein Program um zu funktionieren. Überraschung: Die
Programmausführung beginnt auf Assembler Ebene nämlich
nicht bei main(). Da passiert vorher schon was. Was denkst
du wo der Code herkommt? Richtig der kommt aus der
Standard Library.

> Die paar Pointer-Operationen sind doch schnell geschrieben.

Klar. Aber wozu das ganze nochmal schrieben, wenn ichs
schon fertig da habe.

Das hier:
1
#include <avr/io.h>
2
3
char Text1[] = { "Ein Text1" };
4
char Text2[] = { "Ein Text2" };
5
6
void mystrcpy( char* dest, char* src )
7
{
8
  while( *src )
9
    *dest++ = *src++;
10
  *dest = '\0';
11
}
12
13
int main()
14
{
15
  mystrcpy( Text1, Text2 );
16
}

verbraucht bei -Os  208 Bytes

Das hier
1
#include <avr/io.h>
2
#include <string.h>
3
4
char Text1[] = { "Ein Text1" };
5
char Text2[] = { "Ein Text2" };
6
7
int main()
8
{
9
  strcpy( Text1, Text2 );
10
}
verbraucht 202 Bytes.

Von wegen: Selber schreiben ist kürzer.
Du solltest Dinge nicht raten, sondern ausprobieren.


von Michael (Gast)


Lesenswert?

> Ich programmiere µCs nach Möglichkeit effizient, wozu brauch ich ne
> ganze Lib für so nen Pillepallekram? Schluckt nur wertvollen
> Programmspeicherplatz.

Das Schöne an LIBs ist ja, daß nur die Routinen gebunden werden, die man 
tatsächlich braucht: nix mit "Schluckt nur wertvollen 
Programmspeicherplatz."

Es gibt auch noch strncpy(), ...

von Karl heinz B. (kbucheg)


Lesenswert?

> Ansonsten ist das ein Array am Ende, was im
> RAM liegt.

Das hängt damit zusammen, dass der AVR eine Harvard
Architektur hat und SRAM und Flash anders adressiert
werden. Bei Prozessoren wo das nicht so ist, zb Z80 + EPROM
kann der Compiler String Literale auch ins ROM legen.

char* Text = "Ein Text";

Das String Literal "Ein Text" liegt im ROM. Im RAM wird der
Speicher für den Pointer angelegt und mit der Adresse im ROM
initialisiert.

const char* Text = "Ein Text";

Ist identisch zu obigen. Eigentlich ist das sogar die richtige
Schreibweise. Das der Compiler das Vorhergehende überhaupt
akzeptiert hat historische Ursachen: Eigentlich ist die
erste Version falsch. Man wollte aber aufwärtskompatibel
bleiben. Daher hat man (ausnahmsweise) erlaubt, dass ein
const char* an einen char* zugewiesen werden kann, auch
wenn das streng genommen falsch ist.

const char* const Text = "Ein Text";

Hier liegt sowohl das String Literal selbst, als auch
der Pointer im ROM.

Auf einem AVR kann man das aber so nicht machen, da ja
Flash und SRAM anders adressiert werden und es für den
Prozessor nicht möglich ist, aus dem Pointerwert zu ermitteln
ob das jetzt ein Zugriff aufs Flash oder aufs SRAM ist.
Also geht man den pragmtischen Weg: Alles kommt ins SRAM.

Das ändert aber nichts daran, was der C Standard dazu zu
sagen hat. Und der sagt lapidar: "String Literale sind konstant.
Ihr Datentyp ist const char*"

von Christian R. (supachris)


Lesenswert?

Hast Recht, hatte es falsch in Erinnerung. Ich hab auch immer die 
Array-Deklaration benutzt.  Dann aber über Pointer auf das Array 
zugegriffen, und vorher die Adresse geholt. Hab´s verwechselt, weil ich 
die kontanten Ausgabestrings immer über die besagte Deklarations mit 
const ins Flash geschoben hab.

Zur Stdlib: Dann hab ich das wohl auch missverstanden. Ich dachte du 
meinst die lib, in der halt diese ganzen String-Sachen drin sind. Sollte 
wohl genauer lesen ;)

Ich wollte für mein Projekt mal diese String-Funktionen benutzen (GCC). 
Als ich sie zugelinkt hatte, war das Programm gleich ziemlich 
aufgeblasen, dann hab ich mir das Vergleichen der Strings selber 
geschrieben, hat viel weniger gebraucht. Vielleicht muss man dem GCC 
erst noch irgendwas sagen, dass der da sinnvoller mit umgeht? Ich hatte 
nur das strcmp benutzt und der hatte da soweit ich mich erinnere knapp 
2k an Programmspeicher mehr.

Eventuell gibts da Unterschiede zwischen dem AVR und dem MSP430 
Compiler. Ich arbeite nur mit den MSPs.

von Falk (Gast)


Lesenswert?

@Karl heinz Buchegger

> Also geht man den pragmtischen Weg: Alles kommt ins SRAM.

Gibt es denn auf dem AVR in C eine Möglichkeit, Konstanten in den Flash 
zu verlegen?

MFG
Falk

von Karl heinz B. (kbucheg)


Lesenswert?

Falk wrote:
> @Karl heinz Buchegger
>
>> Also geht man den pragmtischen Weg: Alles kommt ins SRAM.
>
> Gibt es denn auf dem AVR in C eine Möglichkeit, Konstanten in den Flash
> zu verlegen?
>

Guckst du hier

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Vereinfachung_f.C3.BCr_Zeichenketten_.28Strings.29_im_Flash

von Karl heinz B. (kbucheg)


Lesenswert?

> Eventuell gibts da Unterschiede zwischen dem AVR und dem MSP430
> Compiler. Ich arbeite nur mit den MSPs.

Das könnte sein.
Ich benutze den gcc für AVR.

Ob und wie der Linker diese Optimierung machen kann, hängt
beim gcc auch davon ab, wie diese Libraries aufgebaut
werden. In der AVR Version kann er es offensichtlich.


von XMEN (Gast)


Lesenswert?

>void myCopy( const char* source, char* dest )
>{
>  while( *source) {
>    if( *source != ' ' && *source != '\t' ) {
>      *dest = *source;
>      dest++;
>    }
>    source++;
>  }
>
>  *dest= '\0';
>}


hilft mir die obengenannt funk? sodass ich den string in 4 felder 
verteile.

BSP:
String = " hallo wie gehts dir"

String1 = "hallo"
String2 = "wie"
String3 = "gehts"
string4 = "dir"

von Karl heinz B. (kbucheg)


Lesenswert?

Nein.

Denk logisch. Schau dir die Schnittstelle der Funktion
an. Da geht 1 String rein (source) und ein String raus (dest).
Wie soll die Funktion also den String in 4 Felder
unterteilen?

Schau dir die Funktionen strstr() und strtok() an.
Die helfen dir bei deinem Problem.

von XMEN (Gast)


Lesenswert?

ich habe so gemacht ok:
char String1[4][50];
dann eine for schleife genommen dass es zeichenweise kopiert und wenn 
leerzeichen kommt dann soll er auf nächsten String kopieren usw.
es hat funktioniert.
danke

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.