Forum: Mikrocontroller und Digitale Elektronik Strings schreiben und entleeren


von Problemmensch (Gast)


Lesenswert?

Hallo Ihr,

ich habe in einer UART-Funktion einen Punkt, welcher mir das aktuell 
anstehende Zeichen liefert und in einen Buffer schreibt.
Dieser Buffer ist so definiert uart0_command_buffer[6];
Jetzt hab ich noch einen Counter, welcher immer nach reinschreiben 
inkrementiert wird.
Dieser gibt sozusagen immer an, welche stelle als nächstes beschrieben 
wird, ist dieser aber == 5, wird das Ende des Strings geschrieben.

Nach dieser Funktion werte ich im Hauptprogramm den String aus. Es 
klappt alles perfekt.
Danach lösche ich den String, bzw setze den gesamten Inhalt auf NULL.
Nur wie mache ich das ganz genau?!

Ich habe derzit:
1
    // String wieder komplett entleeren
2
    uart0_command_buffer[0] = 0;
3
    uart0_command_buffer[1] = 0;
4
    uart0_command_buffer[2] = 0;
5
    uart0_command_buffer[3] = 0;
6
    uart0_command_buffer[4] = 0;
7
    uart0_command_buffer[5] = 0;
8
    uart0_command_buffer[6] = 0;

Der Compiler bringt mir aber eine Meldung, dass ich über den Bereich des 
Arrays bin.

Wie leere ich den String perfekt?!

Hoffe jemand kann mir genauer helfen.

von Alfred (Gast)


Lesenswert?

Hallo,

mach es mit memset()!

Beste Grüße

Alfred

von hubert (Gast)


Lesenswert?

Klar... Du hast als Buffer ein Array mit 6 Elementen definiert. Und 
schreiben willst Du in Elemet [0] bis einschließlich Element [6]. Das 
sind zusammen 7 Elemente.

Ich würde es so machen:

for (i=0; i<6; i++)
    uart0_command_buffer[i] = 0;

Liest sich leichter und wird vom Compiler eh anhand seiner Regeln 
entweder schnell oder klein optimiert.

von Alfred (Gast)


Lesenswert?

und... wenn Du buffer[6] deklarierst, ist buffer[6] ein ungültiger 
Index!

Es geht bei 0 los!

von hubert (Gast)


Lesenswert?

Stimmt.... memset() ist auch gut.

von Problemmensch (Gast)


Lesenswert?

Okay,

danke schonmal, was genau macht die Funktion memset(); ??
Und, wenn ich jetzt unsigned char XXX[6]; schreibe definiere ich ein 
Array mit 6 Einträgen, also 0-5 oder?

Und das Ende des Strings schreib ich ja als XXX[Y] = '\0'
Ist das dann ein Zeichen? Eigentlich dann ja schon oder?

Danke nochmal!

von hubert (Gast)


Lesenswert?

Problemmensch schrieb:
> danke schonmal, was genau macht die Funktion memset(); ??

google: man memset

> Und, wenn ich jetzt unsigned char XXX[6]; schreibe definiere ich ein
> Array mit 6 Einträgen, also 0-5 oder?

ja

> Und das Ende des Strings schreib ich ja als XXX[Y] = '\0'
> Ist das dann ein Zeichen? Eigentlich dann ja schon oder?

ja, ist noch eines, es braucht auch seinen Platz. Es kennzeichnet in C 
das Ende eines Strings.

von Problemmensch (Gast)


Lesenswert?

Okay, also ist es genau EIN Zeichen. Also 5 Zeichen + das Ende des 
Strings = 6, also unsigned char XXX[6].

Wie sieht das Ende eines Strings aus? Ich schreibe ein \0 rein, aber was 
ist an der Stele vom System überhaupt drin?
Ich habe da irgendwie ein kleines Verständnisproblem -.-

von hubert (Gast)


Lesenswert?

Es ist ein Byte, bei dem alle Bits 0 sind. Dieser Sonderfall ist dafür 
reserviert, das Ende des Strings zu kennzeichnen.

Du kannst auch foo[6] = 0; schreiben.

von Problemmensch (Gast)


Lesenswert?

Achso okay!
Perfekt, danke!

von Klaus W. (mfgkw)


Lesenswert?

Problemmensch schrieb:
> danke schonmal, was genau macht die Funktion memset(); ??

An einigen ganz wenigen ausgesuchten Stellen im Internet und
in der Doku deines Systems ist memset() möglicherweise dokumentiert.


> Und, wenn ich jetzt unsigned char XXX[6]; schreibe definiere ich ein
> Array mit 6 Einträgen, also 0-5 oder?

Genau.

>
> Und das Ende des Strings schreib ich ja als XXX[Y] = '\0'
> Ist das dann ein Zeichen? Eigentlich dann ja schon oder?

Ja.

von Klaus W. (mfgkw)


Lesenswert?

Problemmensch schrieb:
> Wie sieht das Ende eines Strings aus? Ich schreibe ein \0 rein, aber was
> ist an der Stele vom System überhaupt drin?

Vorher? Je nachdem, was halt vorher mit dem Speicher passierte
bzw. wofür er vorher verwendet wurde.
Danahc natürlich die 0.


> Ich habe da irgendwie ein kleines Verständnisproblem -.-

Es gibt Bücher, in denen die Merkwürdigeiten von C mehr oder
weniger gut beschrieben sind :-)

von Nico S. (nico22)


Lesenswert?

In diesem Fall aber foo[5] = 0; denn das Array hat nur sechs Elemente 
(inklusive der Null!). Daher ist [6] schon außerhalb des Arrays. Das hat 
nichts mit der Null zu tun.

hubert schrieb:
> Du kannst auch foo[6] = 0; schreiben.

von Helmut L. (helmi1)


Lesenswert?

Es reicht auch an der Position [0] vom String eine '\0' reinzuschreiben.
Du brauchst nicht alle Zeichen zu loeschen.

von Klaus W. (mfgkw)


Lesenswert?

hubert schrieb:
> Du kannst auch foo[6] = 0; schreiben.

Aber natürlich nicht, wenn es als char foo[6] definiert wurde.

von hubert (Gast)


Lesenswert?

Nico Sch. schrieb:
> In diesem Fall aber foo[5] = 0; denn das Array hat nur sechs Elemente
>
> (inklusive der Null!). Daher ist [6] schon außerhalb des Arrays. Das hat
>
> nichts mit der Null zu tun.
>
>
>
> hubert schrieb:
>
>> Du kannst auch foo[6] = 0; schreiben.

Stinmmt. Jetzt bin ich in die gleiche Falle getappt... :-S

von Problemmensch (Gast)


Lesenswert?

Nehem ich dann für ein String-Array einen unsigned char oder nur einen 
char?

von Klaus (Gast)


Lesenswert?

Für Zeichen nimmst du einfach char.

Und um es nochmal deutlich zu sagen: Um einen String zu leeren ist die 
beste Lösung immernoch ein einzelnes
1
uart0_command_buffer[0] = 0;

von df1as (Gast)


Lesenswert?

Wenn es aber doch der Wunsch nach "vollständigem Entleeren" ist: Den 
'sizeof'-Operator nehmen! Dann ist man unabhängig von der Größe - hat 
diese nur an einer Stelle definiert - oder alternativ für die Größe ein 
#define nehmen. Wenn man viele verschieden große Arrays hat, ist 
'sizeof' schon übersichtlicher.

Entweder:
1
#define number_of_elements(a) (sizeof (a)/sizeof (a[0]))
2
unsigned char uart0_command_buffer[6]; // egal, wie groß ...
3
int           i;
4
5
for (i = 0; i < number_of_elements (uart0_command_buffer); i++)
6
  uart0_command_buffer[i] = 0;

(Das Teilen durch die Größe eines Einzelelements kann man sich bei 
'char' allerdings sparen. Gehört der Vollständigkeit halber aber dazu.)

Oder (Einzelelementgröße egal):
1
unsigned char uart0_command_buffer[6]; // egal, wie groß ...
2
3
memset (uart0_command_buffer, 0, sizeof (uart0_command_buffer));

von Klaus W. (mfgkw)


Lesenswert?

Noch netter wäre ein const size_t statt #define, aber sonst ACK.

von André H. (andrekr)


Lesenswert?

hubert schrieb:
> Es ist ein Byte, bei dem alle Bits 0 sind. Dieser Sonderfall ist dafür
> reserviert, das Ende des Strings zu kennzeichnen.

Diese grundsätzliche Aussage finde ich immer verwirrend und 
möglicherweise ist das auch der Grund für die Verwirrung des OP.

Es ist Konvertion, daß die üblichen String-Funktionen (z.B. strcpy) auf 
das 0 als Markierung für das Ende des Strings reagieren und daß, wenn 
man "bla" schreibt, anschließend b l a \0 im Speicher steht, aber C 
hindert niemanden daran, über ein \0 hinweg zu lesen oder zu schreiben. 
Es wird auch nicht etwa implizit Platz dafür reserviert oder ähnliches.

von Peter D. (peda)


Lesenswert?

Alles hinter dem Null-Byte gehört nicht mehr zum String.
Es reicht also völlig, nur das erste Byte mit 0 zu beschreiben.

Oftmals braucht man einen String aber nicht zu leeren.
Du empfängst bis zum Endezeichen, ersetzt es mit 0 und erst dann wird 
der String ausgewertet. Es ist ja unsinnig, einen String auszuwerten, 
wenn er noch nicht alle Zeichen enthält.


Peter

von df1as (Gast)


Lesenswert?

Klaus Wachtler schrieb:
> Noch netter wäre ein const size_t statt #define, aber sonst ACK.

Warum? Eine Elementanzahl ist eher noch 'int' als 'size_t' (meistens 
ohnehin aufgelöst als 'unsigned int') oder einfach nur eine Zahl. Oder 
soll ich die Array[byte]größe damit festlegen und die Elementeanzahl 
wiederum ausrechnen?
1
const size_t mySize = 13; // mal ungerade probieren?
2
3
unsigned short ausArray[mySize / sizeof (unsigned short)];

von Karl H. (kbuchegg)


Lesenswert?

df1as schrieb:
> Klaus Wachtler schrieb:
>> Noch netter wäre ein const size_t statt #define, aber sonst ACK.
>
> Warum?

Weil du #define vermeiden möchtest.
Ein #define wird vom Preäprozessor aufgelöst. Ein size_t ist aber in den 
Debug Symboltabellen immer noch vorhanden, da es eine Variable ist.

> Eine Elementanzahl ist eher noch 'int' als 'size_t' (meistens
> ohnehin aufgelöst als 'unsigned int')

meistens. Aber nicht immer.
Mit einem size_t musst du dir darüber aber keine Gedanken machen.


> soll ich die Array[byte]größe damit festlegen und die Elementeanzahl
> wiederum ausrechnen?

Das ist quatsch.
Denn bei der Definition eines Arrays gibt man immer die Anzahl Elemente 
an.
Anders rum wird ein Schuh daraus:
Hat man ein Array, welches durch die Initialisierung automatisch vom 
Compiler dimensioniert wird, dann benutzt man ein sizeof Konstrukt um 
die tatsächliche Arraydimensionierung festzustellen.

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.