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"
> 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...
> 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.
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.
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.
> 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()...
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.
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 :-)
> 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 :-)
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
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
charaChar[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
chariI=0;
16
for(;iI<sizeof(aChar);++iI)
17
{
18
if(aChar[iI]=='\n')
19
{
20
// jetzt aus den vorhergehenden Zeichen den String erzeugen.?.?.?
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];
}
>> 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.
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?
>> 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.
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
unsignedchariI=0;
2
unsignedchariJ;
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.
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
charNextString[20];
4
unsignedchari;
5
charc;
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 :-)
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
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
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.
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)