mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik keil array => string


Autor: Heinz B. (hez)
Datum:

Bewertung
0 lesenswert
nicht 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"

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Stefan_KM (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Willst du den String ausgeben? Auf ein Display oder so? Oder an den PC 
schicken?

Autor: Random ... (thorstendb) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Klaus Falser (kfalser)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Random ... (thorstendb) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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()...

Autor: Random ... (thorstendb) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

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

Bewertung
0 lesenswert
nicht 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 :-)

Autor: Random ... (thorstendb) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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 :-)

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

Bewertung
0 lesenswert
nicht 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

Autor: Heinz B. (hez)
Datum:

Bewertung
0 lesenswert
nicht 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:
char aChar[16];
// Testdaten (simuliert Daten von Seriellen):
aChar[0]='a';
aChar[1]='b';
aChar[2]='c';
aChar[3]='\n';
aChar[4]='d';
aChar[5]='e';
aChar[6]='f';
aChar[7]='g';
aChar[8]='\n';
aChar[9]='h';
aChar[10]='\n';
// Array durchlaufen:
char iI=0;
for(;iI<sizeof(aChar);++iI)
{
   if(aChar[iI]=='\n')
   {
      // jetzt aus den vorhergehenden Zeichen den String erzeugen.?.?.?
   }
}

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

Bewertung
0 lesenswert
nicht 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];
}

Autor: Heinz B. (hez)
Datum:

Bewertung
0 lesenswert
nicht 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.

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

Bewertung
0 lesenswert
nicht 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?

Autor: Heinz B. (hez)
Datum:

Bewertung
0 lesenswert
nicht 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.

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

Bewertung
0 lesenswert
nicht 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
unsigned char iI=0;
unsigned char iJ;
char* EinzelString = NULL;    // 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 );
     free( Einzelstring );
     EinzelString = NULL;
     iJ = 0;
   }
   else {
     EinzelString = realloc( iJ + 2 );  // Platz für den \0 auch gleich mitnehmen
     if( !Einzelstring )
       break;
     EinzelString[iJ++] = aChar[iI];
  }
}

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.

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

Bewertung
0 lesenswert
nicht 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
  ...

  char NextString[20];
  unsigned char i;
  char c;

  i = 0;
  c = getCharacter();
  while( c != '\n' ) {
    NextString[i++] = c;
    c = getCharacter();
  }
  NextString[i] = '\0';

  // jetzt hast du in NextString den nächsten komplett empfangenen String
  // der mit einem \n abgeschlossen wurde

  printf( "%s", NextString );

  ...

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

Autor: Heinz B. (hez)
Datum:

Bewertung
0 lesenswert
nicht 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

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

Bewertung
0 lesenswert
nicht 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_fu...

Autor: Heinz B. (hez)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: Heinz B. (hez)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schon notiert. Danke.

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.