Strings schreiben und entleeren

Gast #2051047
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.
Gast #2051058
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.
Gast #2051070
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!
Gast #2051074
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.
Gast #2051085
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 -.-
#2051093
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.
#2051097
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 :-)
Gast #2051104
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
Gast #2051189
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));
#2051244
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.
#2051246
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
Gast #2051252
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)];
#2051298
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren