String zurücksetzen

#4921319
Lesenswert?

Hallo Forum,

ich habe hier gelesen, dass man in C Strings durch

char text[80];
text[0] = "\0";

zurücksetzt. Das funktioniert bei mir aber nicht. text behält seinen 
ursprünglichen Wert bei.

Ab Index 1 geht es aber. Zum Beispiel
text[1] = "\0";
Dann ist text nur noch 1 Zeichen lang.
Aber warum geht es nicht mit 0 ? Mache ich da etwas falsch ?

Das ganze läuft auf einem Arduino Leonardo.

Viele Grüße
Gast #4921364
Lesenswert?

text[0] = 0; /* das ist ok */

Zeichenketten mit "" sind immer ein String, haben also nichts an text[0] 
verloren.

Ein Zeichen '0' oder '\0' ist erstmal int. Wäre zwar in Ordnung, schafft 
aber mehr Verwirrung als Klarheit (und Fehler, wie im ersten Beispiel).
Gast #4921367
Lesenswert?

Was bedeutet "Das funktioniert bei mir aber nicht."
Woher weißt Du, dass das nicht funktioniert.
Gibst Du den Text hinterher aus, oder liefert strlen(text) was anderes 
als 0.
Zeig doch mal was Du tust um zu finden, dass das nicht funktioniert.
#4921371
Lesenswert?

sowohl
  text[0] = 0x00;
als auch
  text[0] = 0;
haben das gleiche Verhalten. mit text[1] geht es in beiden Fällen mit 
text[0] ändert sich text nicht.

Wenn man die beiden ersten Felder nullt funktioniert es, also
  text[0] = '\0';
  text[1] = '\0';
Dann wird der ganze string Null.

Kann es sein, dass das beim Arduino irgendwie speziell ist ? in C sollte 
ja   text[0] = '\0'; (oder 0x00 oder einfach 0) funktionieren.

Edit:
"Was bedeutet "Das funktioniert bei mir aber nicht.""
Ich gebe den Sting aus und er ist unverändert
#4921380
Lesenswert?

Belo L. schrieb:
> Edit:
> "Was bedeutet "Das funktioniert bei mir aber nicht.""
> Ich gebe den Sting aus und er ist unverändert

Dann zeig den Code!

Der String wird auch nicht komplett gelöscht, sondern nur seine Länge 
auf Null gesetzt.

Die Stringfunktionen der C-Standard-Bibliothek kommen damit klar.
Die allermeisten Nutzerfunktionen auch.

Also, zeig deinen minimalen, fehlerhaften Code.
#4921386
Lesenswert?

gerne, hier der Code:

char ccc;
char zeile[100];
int iii = 0;
void setup() {
    Serial.begin(9600);
}

void loop() {
    ccc='\0';
    if (Serial.available() > 0) {
        ccc = Serial.read();
        if (ccc == 13) {
            Serial.println(zeile);
            zeile[0] = '\0';
            iii = 0;
        }else{
            zeile[iii]=ccc;
            iii++;
        }
    }
}
Gast #4921395
Lesenswert?

Belo L. schrieb:
> gerne, hier der Code:
>
> char ccc;
> char zeile[100];
> int iii = 0;
> void setup() {
>     Serial.begin(9600);
> }
>
> void loop() {
>     ccc='\0';
>     if (Serial.available() > 0) {
>         ccc = Serial.read();
>         if (ccc == 13) {
>             Serial.println(zeile);
>             zeile[0] = '\0';
>             iii = 0;
>         }else{
>             zeile[iii]=ccc;
>             iii++;
>         }
>     }
> }

Ahhh, Arduino...
füge mal hinter
1
iii++;
eine Zeile ein
1
zeile[iii]='\0';
Gast #4921405
Lesenswert?

Eine Idee wäre :

Keine Ahnung wo Deine seriellen Daten herkommen.
Wenn es ein Terminal ist, oder eine Applikation ,die als Zeilenende
CR+LF sendet, dann würde dein CR (13) den String an Zeile[0] zwar mit 
0x0 beschreiben, das sofort nachfolgende LF (10) würde aber sofort 
Zeile[0] wirde überschreiben.
Wenn Du hinter jedem neuen Zeichen das reinkommt noch zusätzlich ein 0x0 
schreiben würdest, dann könnte man das besser sehen.

( zeile[iii]=ccc;   )
( zeile[iii+1]=0x0; )
Gast #4921417
Lesenswert?

Weil man eine String nicht "zurücksetzen" kann.
Der String endet einfach mit dem 0x0.

Wenn Du nun das erste Zeichen des Strings mit 0x0 beschreibst, dann ist 
der String 0 Zeichen lang.
Sobald Du etwas anderes in die erste Stelle des Strings schreibst, ist 
das 0x0 weg ( überschieben mit dem neuen Zeichen ) und es gibt keine 
Kennung mehr wo der String endet.

Wenn du aber hinter jedes Zeichen, dass du an den String anhängst ein 
0x0 schreibst, dann hast Du damit dafür gesorgt, dass der String hinter 
dem eben angefügten Zeichen endet.
Gast #4921418
Lesenswert?

Das ist dein alter String:
ABCDEFGH-

- soll ein '\0' symbolisieren.

Nachdem du die Zeile ausgegeben hast setzt du text[0] auf '\0'
Jetzt hast du
-BCDEFGH-

Sobald das erste Zeichen kommt (ein 'X') sieht's so aus:
XBCDEFGH-

Mit der Änderung machst du nun folgendes:
X-CDEFGH-

Noch ein Zeichen Y
XY-DEFGH-


Ausgegeben wird der String immer bis zum '\0'
#4921447
Lesenswert?

"aber bei Arduino gehe ich immer erst mal von einem
Einsteiger/einer Einsteigerin aus"

Warum Einsteiger ? Macht ein "Profi" nichts mit Arduino ?

Ich bin aber in der Tat Einsteiger in C, kenne aber ein paar andere 
Programmiersprachen recht gut. Da ist das mit den Variablen aber völlig 
anders. Geht ja bei C schon in Richtung Assembler.
Gast #4921567
Lesenswert?

Nur als Anmerkung:

Dein Code hat bisher keine 0 ans Ende eigefügt.
Damit hatten Deine Strings bisher überhaupt kein Ende.
Serial.println hat nur Funtkioniert, weil der C-Compiler zeile zu Beginn 
mit Nullen geflutet hat.

Die Fehlende 0 am Ende eines Strings ist eines der Speicherfehler in 
C.

Du müsstest hier sogar jedesmal fragen, ob iii <99 ist. Und wenn nicht, 
dann das Einlesen sofort abbrechen bzw. "neu" starten, ggf. mit einem 
zusätzlichen Hinweistext.
Gast #4921712
Lesenswert?

Belo L. schrieb:
> "Die Fehlende 0 am Ende eines Strings ist eines der Speicherfehler in
> C."
>
> Wird also als Fehler gewertet.

Das ist ein Fehler, der eher in Sonderfällen unglücklicherweise nicht 
zum Programmabsturz führt.

> Welche gibt es denn noch ?

Hängende Zeiger. Einfaches Beispiel (ohne dyn. Allokation):

int* foo()
{
  int bla = 99;
  // ...
  return &bla;
}

- Nicht initialisierte Zeiger.
- Dereferenzieren von NULL-Zeigern.

Generelle häufige Fehler:
- Keinen Platz für den 0-Terminator in C-Strings lassen.
- Vergleichen von C-Strings mit ==.
- Vergessen von break in switch.
- char- und String-Literale verwechseln.
- Off-by-one-Fehler.
- Unbeabsichtiges Semikolon nach Schleifenkopf.
- Ungewollte Integer-Division (double x = 1/2;).
Moderator Persönliche Seite #4922118
Lesenswert?

Walter S. schrieb:
> da müsste auch eine Warnung kommen.

Kommt auch:
1
#include <stdio.h>
2

3
int main()
4
{
5
    char text[100];
6

7
    text[0] = "\0";
8

9
    return 0;
10
}
1
$ cc b.c
2
b.c: In function 'main':
3
b.c:8:13: warning: assignment makes integer from pointer without a cast [enabled by default]

> Vor allem als Anfänger sollte man Warnungen immer als Fehler ansehen

Ja, leider werden sie gerade von Anfängern ignoriert, weil sie diese 
einfach nicht verstehen.
#4922234
Lesenswert?

Frank M. schrieb:
> Walter S. schrieb:
>> Vor allem als Anfänger sollte man Warnungen immer als Fehler ansehen
>
> Ja, leider werden sie gerade von Anfängern ignoriert, weil sie diese
> einfach nicht verstehen.

Dabei ist es recht einfach, nach dem Text einer Warnung zu googeln. 
Meistens bekommt man dann schon eine recht gute Vorstellung wie man den 
Code verbessern kann.
#4922431
Lesenswert?

Belo L. schrieb:
> gerne, hier der Code:
>
> char ccc;
> char zeile[100];
> int iii = 0;

Uff, gewöhne dich an
- deine Variabelen bedeutungsvolle Namen zu geben
- sinnvolle Kommentare einzufügen.
Kostet nichts extra, spart dir aber später eine ganze Menge 
Kopfschmerzen.
1
char zeile[100];
2
char zeichen;
3
int  index;
4

5
void setup()
6
{
7
    Serial.begin(9600);
8
    zeichen = 0;
9
}
10

11
void loop()
12
{
13
    if (Serial.available() > 0)
14
    {
15
        zeichen = Serial.read();
16

17
        if (zeichen == 13)
18
        {
19
            // Zeilenumbruch
20
            Serial.println(zeile);
21

22
            index = 0;
23
            zeile[index] = 0;
24
        }
25
        else if(index < 99)
26
        {
27
            // Passt noch - füge zeichen hinzu
28
            zeile[index] = zeichen;
29
            index ++;
30
            zeile[index] = 0;
31
        }
32
        else
33
        {
34
            // Kein Zeilenumbruch aber zeichen passt nicht mehr
35
            // --> ignorieren. Tue nix
36
        }
37
    }
38
}
#4922460
Lesenswert?

Vielen Dank für das Programm.

Das letzte else hast du wahrscheinlich nur zur Verdeutlichung eingefügt, 
oder hat das irgendeine Bedeutung ? Ich würde das nämlich normalerweise 
weglassen.

Ist zeile[index] = 0;
genau so "gut" wie zeile[index] = '\0'; ?
Das findet man ja sonst meistens.

Ich gebe Variablen normalerweise schon sinnvolle Namen. Für Index 
schreibe ich immer iii (anstelle von einfach i, damit man es besser 
finden kann) und ccc ist ein einzelner char. Hat sich bei mir so 
eingebürgert. Andere Variablen benenne ich eigentlich immer sinnvoll.
#4923169
Lesenswert?

Belo L. schrieb:
> Ist zeile[index] = 0;
> genau so "gut" wie zeile[index] = '\0'; ?
> Das findet man ja sonst meistens.

Zweiteres ist etwas expressiver, weil man gleich sieht, dass da nicht 
einfach die Zahl 0 reingeschrieben werden soll, sondern der 
Nullterminator eines Strings. Ansonsten ist es aber gleichwertig.
In C ist 0 und '\0' der gleiche Wert, jeweils ein int mit dem Wert 0. In 
C++ gibt es einen Unterschied beim Typ, da '\0' dort vom Typ char ist. 
Spielt aber bei der obigen Zeile keine Rolle.

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