Forum: Mikrocontroller und Digitale Elektronik keil array => string


von Heinz B. (hez)


Lesenswert?

hello,

kann man im Keil aus einem Array einen String erzeugen?

Das Problem: erst mein Programm ermittelt, aus wie vielen Elementen 
dieses Array besteht.

Das Array kann so aussehen:
[0] = 'x';

Oder so:
[0] = 'a';
[1] = 'b';

Oder auch mit mehreren Elementen.

Wie viele es sind, hängt davon ab, wie viele ich von außen (über 
serielle Schnittstelle) bekomme. Es soll aber immer ein String draus 
werden.

Geht das?

EDIT:

Vielleicht sollte ich noch einen Pseudocode dazuschreiben, damit klar 
ist, was ich meine:

char sText[];
sText="";
sText+="a";
sText+="b";
sText+="c";

Am Schluss soll in sText stehen: "abc"

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> kann man im Keil aus einem Array einen String erzeugen?
Ein String an sich ist in C bereits ein Array aus char   :-o

Also wirst du nur sowas wie strcpy() oder strncpy() oder memcpy() 
brauchen...

von Stefan_KM (Gast)


Lesenswert?

Willst du den String ausgeben? Auf ein Display oder so? Oder an den PC 
schicken?

von Random .. (thorstendb) Benutzerseite


Lesenswert?

> Ein String an sich ist in C bereits ein Array aus char   :-o
nicht ganz, ein string ist immer um ein element grösser als ein reines 
char array, da der abschluss-character (0, '\0') noch mit gespeichert 
werden muss.

char string[10];

string[0..8] ==> zeichen
string[9] = 0

Latürnich kann die null an jeder beliebigen stelle im array stehen, das 
Beispiel zeigt nur den maximalfall.


> kann man im Keil aus einem Array einen String erzeugen?
Ist eigentlich nur std:C

Ist das Array voll, müsstest du einen

memcpy(array, neuesArray, len);
neuesArray[len]=0;

machen, dabei muss neuesArray um eins grösser sein als array.

Danach kannst du mit den str-funktionen arbeiten, da die alle auf die 
Abschluss-0 reagieren.


---
Anmerkung:

Ich bin in meinen Projekten schon lange auf Strings anstelle 
irgendwelcher arrays und Indizes ausgewichen, da mit der Definition, 
dass ein String immer mit 0 abschliesst, einiges sehr viel einfacher 
wird.

Z.B. übergibt man nur den Stringpointer, und alles rennt. Lediglich bei 
einem LineEdit sollte man sich die Cursorposition merken und temporär 
einen len :-)


VG,
/th.

von Klaus F. (kfalser)


Lesenswert?

Lothar Miller schrieb:
>> kann man im Keil aus einem Array einen String erzeugen?
> Ein String an sich ist in C bereits ein Array aus char   :-o
>
Und zur Erinnerung : das letzte Element ist ein Null Character \0.
Daran wird die Länge erkannt.

von Random .. (thorstendb) Benutzerseite


Lesenswert?

Nachtrag (verdammt, warum geht hier kein Edit wenn der Beitrag nicht 
unten steht??)

> Also wirst du nur sowas wie strcpy() oder strncpy() oder memcpy()
> brauchen...

Diese funktionen haut dir - wenn du Glück hast - dein OS um die Ohren 
(mit Ausnahme von vllt. memcpy), da sie über die Arraylänge hinaus bis 
zum Crash oder der nächsten NULL arbeiten würden.

VG,
/th.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> Diese funktionen haut dir - wenn du Glück hast - dein OS um die Ohren
Für und gegen solche Fälle hilft i.A. die Funktion der Funktion vor 
deren Verwendung auf Eignung zu überprüfen.

> Diese funktionen haut dir - wenn du Glück hast - dein OS um die Ohren
Sieh mal nach, was strncpy() macht.
Die ist mindestens genausogut wie memcpy()...

von Random .. (thorstendb) Benutzerseite


Lesenswert?

Lothar Miller schrieb:
>> Diese funktionen haut dir - wenn du Glück hast - dein OS um die Ohren
> Sieh mal nach, was strncpy() macht.
> Die ist mindestens genausogut wie memcpy()...

Nicht ganz ... strcpy wird "nicht" funktionieren, wenn der String nicht 
mit NULL abgeschlossen ist. strcpy sollte in etwa sein:

memcpy(dest, src, strlen(src));

und genau da liegt die Krux: strlen kann keine sinnvolle string Länge 
für ein nicht NULL-terminiertes Array zurückliefern, also kopiert dir 
der oberhalb des dest Speichers alles mögliche über und crashed (wenn du 
Glück hast) irgendwann.

von Karl H. (kbuchegg)


Lesenswert?

Random ... schrieb:
> Lothar Miller schrieb:
>>> Diese funktionen haut dir - wenn du Glück hast - dein OS um die Ohren
>> Sieh mal nach, was strncpy() macht.
>> Die ist mindestens genausogut wie memcpy()...
>
> Nicht ganz ... strcpy wird "nicht" funktionieren,

genau lesen.
Lothar schrub:  strncpy   ... mit einem n in der Mitte


> strcpy sollte in etwa sein:
>
> memcpy(dest, src, strlen(src));

recht weit her ist es aber mit deinen C Kenntnissen auch nicht :-)

von Random .. (thorstendb) Benutzerseite


Lesenswert?

> genau lesen.
> Lothar schrub:  strncpy   ... mit einem n in der Mitte

ok, sry, überlesen. Dann pfeift's einem nicht in falschen Speicher 
(vorausgesetzt man gibt ein korrektes "n" an), aber es wird immer das 
gesamte Array kopiert.

>> memcpy(dest, src, strlen(src));
> recht weit her ist es aber mit deinen C Kenntnissen auch nicht :-)
Danke für die Blumen! Dafür bist du ja auch Mod und ich nicht :-)

Wo liegt in der Funktionsweise der Unterschied?
ok, hab was vergessen, aber es ging nur um eine Illustration des 
Problems, nicht um die Bereitstellung einer Lösung:

dest[len] = 0;

---
> genau lesen.
> Lothar schrub:  strncpy   ... mit einem n in der Mitte
recht weit her ist es aber mit deinen Deutsch Kenntnissen auch nicht :-)

von Karl H. (kbuchegg)


Lesenswert?

Random ... schrieb:
>> genau lesen.
>> Lothar schrub:  strncpy   ... mit einem n in der Mitte
>
> ok, sry, überlesen. Dann pfeift's einem nicht in falschen Speicher
> (vorausgesetzt man gibt ein korrektes "n" an), aber es wird immer das
> gesamte Array kopiert.

Nicht ganz.
Es wird der String vollständig kopiert oder der Teil, der noch in die 
Destination hineinpasst. Je nachdem was zutrifft.

Das einzig unangenehme bei strncpy ist die Tatsache, dass im 2-ten Fall 
der String kein String mehr ist. strncpy fügt bei Überlaufen der 
Destination kein \0 an.

>>> memcpy(dest, src, strlen(src));
>> recht weit her ist es aber mit deinen C Kenntnissen auch nicht :-)
> Danke für die Blumen! Dafür bist du ja auch Mod und ich nicht :-)
>
> Wo liegt in der Funktionsweise der Unterschied?

Dass deine memcpy Variante die \0 nicht mitkopiert.
Wenn schon, dann entspricht

  memcpy(dest, src, strlen(src)+1);

einem strcpy. (Beliebter Fehler: wenn ein strlen benutzt wird um damit 
irgendetwas zu steuern, braucht man praktisch immer strlen(x)+1)

Wer allerdings strcpy mit memcpy implementiert, sollte gleich erschlagen 
werden

void myStrCpy( char *dest, const chat* src )
{
  while( *src )
    *dest++ = *src++;

  *dest = '\0';
}


>> Lothar schrub:  strncpy   ... mit einem n in der Mitte
> recht weit her ist es aber mit deinen Deutsch Kenntnissen auch nicht :-)

:-)
Touche

von Heinz B. (hez)


Lesenswert?

Hab hier kaum was verstanden. Aber ich glaube, ihr habt mich sowieso 
nicht verstanden, was ich versuche. Liegt aber sicher an mir. Habe mich 
sicher falsch ausgedrückt. Weiterer Versuch :)

Ich bekomme über die Serielle z. B.:

'a' 'b' 'c' '\n' 'd' 'e' 'f' 'g' '\n' 'h' '\n'

Die Zeichen landen in einem Array.
Jetzt habe ich versucht, die Zeichen einzeln auszulesen und bei jedem \n 
einen String aus den vorhergehenden Zeichen zu machen. Also:

'a' 'b' 'c' '\n' => "abc"
'd' 'e' 'f' 'g' '\n' => "defg"
'h' => "h"

Ich würde das gerne in einer Schleife machen:
1
char aChar[16];
2
// Testdaten (simuliert Daten von Seriellen):
3
aChar[0]='a';
4
aChar[1]='b';
5
aChar[2]='c';
6
aChar[3]='\n';
7
aChar[4]='d';
8
aChar[5]='e';
9
aChar[6]='f';
10
aChar[7]='g';
11
aChar[8]='\n';
12
aChar[9]='h';
13
aChar[10]='\n';
14
// Array durchlaufen:
15
char iI=0;
16
for(;iI<sizeof(aChar);++iI)
17
{
18
   if(aChar[iI]=='\n')
19
   {
20
      // jetzt aus den vorhergehenden Zeichen den String erzeugen.?.?.?
21
   }
22
}

von Karl H. (kbuchegg)


Lesenswert?

Heinz B. schrieb:

> for(;iI<sizeof(aChar);++iI)
> {
>    if(aChar[iI]=='\n')
>    {
>       // jetzt aus den vorhergehenden Zeichen den String erzeugen.?.?.?

Wo erzeugst du den String?
In welchem Array?

>    }
> }


unsigned char iI=0;
unsigned char iJ;
char EinzelString[10];    // das nimmt einen einzelnen String auf

iJ = 0;
for(;iI<sizeof(aChar);++iI)
{
   if(aChar[iI]=='\n')
   {
     EinzelString[iJ] = '\0';
     // jetzt ist es ein String. Mach was damit
     printf( "%s", EinzelString );
     iJ = 0;
   }
   else
     EinzelString[iJ++] = aChar[iI];
}

von Heinz B. (hez)


Lesenswert?

>> Wo erzeugst du den String?
Das ist ja mein Problem, das ich habe. Ich erzeuge den noch nirgends, 
weil ich nicht weiß, wie ich das machen soll.

>> char EinzelString[10];    // das nimmt einen einzelnen String auf
Ein Array mit einer festen Länge zu definieren würde ich gerne 
vermeiden, weil die Strings immer unterschiedlich lang sind.

von Karl H. (kbuchegg)


Lesenswert?

Heinz B. schrieb:

>>> char EinzelString[10];    // das nimmt einen einzelnen String auf
> Ein Array mit einer festen Länge zu definieren würde ich gerne
> vermeiden, weil die Strings immer unterschiedlich lang sind.

Dann wirds allerdings kompliziert :-)
Wie "gut Freund" bist du mit malloc und free?

Im Ernst.
Auf einem µC: lege eine Maximalgröße fest und arbeite damit. Ist 
einfacher und auch weniger fehlerträchtig als eine dynamische 
Verwaltung.
Was passiert den mit den Einzelstrings?

von Heinz B. (hez)


Lesenswert?

>> Wie "gut Freund" bist du mit malloc und free?
Oh ... du weißt ja, dass ich mich nicht gut damit auskenne ;)

Aber könntest du mir bitte trotzdem mal ein Beispiel zeigen?

>> Was passiert den mit den Einzelstrings?
Keine Ahnung. Vielleicht mache ich es dann auch gar nicht mit Strings. 
Aber ich würde gerne wissen, wie es geht.

von Karl H. (kbuchegg)


Lesenswert?

Heinz B. schrieb:
>>> Wie "gut Freund" bist du mit malloc und free?
> Oh ... du weißt ja, dass ich mich nicht gut damit auskenne ;)
>
> Aber könntest du mir bitte trotzdem mal ein Beispiel zeigen?


Ehrlich?
Das willst du nicht wirklich :-)

OK
1
unsigned char iI=0;
2
unsigned char iJ;
3
char* EinzelString = NULL;    // das nimmt einen einzelnen String auf
4
5
iJ = 0;
6
for(;iI<sizeof(aChar);++iI)
7
{
8
   if(aChar[iI]=='\n')
9
   {
10
     EinzelString[iJ] = '\0';
11
     // jetzt ist es ein String. Mach was damit
12
     printf( "%s", EinzelString );
13
     free( Einzelstring );
14
     EinzelString = NULL;
15
     iJ = 0;
16
   }
17
   else {
18
     EinzelString = realloc( iJ + 2 );  // Platz für den \0 auch gleich mitnehmen
19
     if( !Einzelstring )
20
       break;
21
     EinzelString[iJ++] = aChar[iI];
22
  }
23
}

Aber ich warne dich eindringlich.
Das öffnet auf einem µC mit seinem sehr begrenzten Speicher die Büchse 
der Pandora. Speicherfragmentierung kann dir da ganz schnell einen 
Strich durch die Rechnung machen und im Endeffekt ist die maximale Länge 
der Strings die du gerade noch bearbeiten kannst dann kleiner als wenn 
du gleich eine statische Allokierung mit einer Maximallänge gemacht 
hättest.

>>> Was passiert den mit den Einzelstrings?
> Keine Ahnung. Vielleicht mache ich es dann auch gar nicht mit Strings.

Das wäre aber gut zu wissen.
Unter Umständen muss man nämlich die Teilstrings gar nicht aus dem 
kompletten rauskopieren. Eine Abfolge von Zeichen, die mit einem \0 
beendet wird, ist in C ein String. Wenn man also in aChar die \0 korrekt 
einsetzt und einen Pointer auf den Anfang der Zeichen hat, kann man den 
Pointer wunderbar an eine stringverarbeitende Funktion übergeben.

von Karl H. (kbuchegg)


Lesenswert?

Aber jetzt kommts mir erst :-)

Du bist doch der Heinz B. mit dem Ringbuffer?
Da macht man das dann allerdings anders (am Prinzip der statischen 
Allokierung würde ich aber trotzdem festhalten)

Du brauchst eine Funktion getCharacter(), die dir das nächste Zeichen 
aus dem Ringbuffer holt. Wenn keines verfügbar ist, muss man 
entscheiden: soll die Funktion warten oder soll sie mitteilen, dass 
nichts da ist. Ich nehme mal den einfachsten Fall: sie wartet
1
  ...
2
3
  char NextString[20];
4
  unsigned char i;
5
  char c;
6
7
  i = 0;
8
  c = getCharacter();
9
  while( c != '\n' ) {
10
    NextString[i++] = c;
11
    c = getCharacter();
12
  }
13
  NextString[i] = '\0';
14
15
  // jetzt hast du in NextString den nächsten komplett empfangenen String
16
  // der mit einem \n abgeschlossen wurde
17
18
  printf( "%s", NextString );
19
20
  ...

Fehlerbehandlung, damit NextString nicht überlaufen wird, wäre noch 
sinnvoll :-)

von Heinz B. (hez)


Lesenswert?

Schaut wirklich kompliziert aus, das Programm.

Wenn ich das jetzt richtig verstanden haben, ist das hier ein korrekter 
String:

char sText[255];
sText[0]='a';
sText[1]='b';
sText[2]='\0';

Und die restlichen leeren Arrayelemente stören dann nicht irgendwie? 
Kann man dann ganz normal mit den String-Funktionen arbeiten?

EDIT: ja genau, ich bin der "ringbuffer-heinz" lach

von Karl H. (kbuchegg)


Lesenswert?

Heinz B. schrieb:
> Schaut wirklich kompliziert aus, das Programm.
>
> Wenn ich das jetzt richtig verstanden haben, ist das hier ein korrekter
> String:
>
> char sText[255];
> sText[0]='a';
> sText[1]='b';
> sText[2]='\0';
>
> Und die restlichen leeren Arrayelemente stören dann nicht irgendwie?
> Kann man dann ganz normal mit den String-Funktionen arbeiten?

Du solltest dir wirklich Literatur zulegen.
In der Zwischenzeit kannst du das als Einführung nehmen
http://www.mikrocontroller.net/articles/FAQ#Wie_funktioniert_String-Verarbeitung_in_C.3F

von Heinz B. (hez)


Lesenswert?

Wunderbar. Womit meine Frage beantwortet wäre. Danke :)
P. S. Literatur habe ich. Ein Büchlein. Leider ein wenig oberflächlich 
und ziemlich alt. Aber grundsätzlich für Anfänger ganz ok, glaube ich.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Heinz B. schrieb:
> Literatur habe ich. Ein Büchlein. Leider ein wenig oberflächlich
> und ziemlich alt. Aber grundsätzlich für Anfänger ganz ok, glaube ich.
Kauf dir irgendeine Ausgabe des K&R, das ist das Standardwerk 
schlechthin.
(Kernighan & Ritchie, Programmieren in C)

von Heinz B. (hez)


Lesenswert?

Schon notiert. 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.