www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Strings schreiben und entleeren


Autor: Problemmensch (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
    // String wieder komplett entleeren
    uart0_command_buffer[0] = 0;
    uart0_command_buffer[1] = 0;
    uart0_command_buffer[2] = 0;
    uart0_command_buffer[3] = 0;
    uart0_command_buffer[4] = 0;
    uart0_command_buffer[5] = 0;
    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.

Autor: Alfred (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

mach es mit memset()!

Beste Grüße

Alfred

Autor: hubert (Gast)
Datum:

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

Autor: Alfred (Gast)
Datum:

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

Es geht bei 0 los!

Autor: hubert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stimmt.... memset() ist auch gut.

Autor: Problemmensch (Gast)
Datum:

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

Autor: hubert (Gast)
Datum:

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

Autor: Problemmensch (Gast)
Datum:

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

Autor: hubert (Gast)
Datum:

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

Autor: Problemmensch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achso okay!
Perfekt, danke!

Autor: Klaus Wachtler (mfgkw)
Datum:

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

Autor: Klaus Wachtler (mfgkw)
Datum:

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

Autor: Nico Sch. (nico22)
Datum:

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

Autor: Helmut Lenzen (helmi1)
Datum:

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

Autor: Klaus Wachtler (mfgkw)
Datum:

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

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

Autor: hubert (Gast)
Datum:

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

Autor: Problemmensch (Gast)
Datum:

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

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
uart0_command_buffer[0] = 0;

Autor: df1as (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
#define number_of_elements(a) (sizeof (a)/sizeof (a[0]))
unsigned char uart0_command_buffer[6]; // egal, wie groß ...
int           i;

for (i = 0; i < number_of_elements (uart0_command_buffer); i++)
  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):
unsigned char uart0_command_buffer[6]; // egal, wie groß ...

memset (uart0_command_buffer, 0, sizeof (uart0_command_buffer));

Autor: Klaus Wachtler (mfgkw)
Datum:

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

Autor: André H. (andrekr)
Datum:

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

Autor: Peter Dannegger (peda)
Datum:

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

Autor: df1as (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?
const size_t mySize = 13; // mal ungerade probieren?

unsigned short ausArray[mySize / sizeof (unsigned short)];

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

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

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.