Forum: PC-Programmierung String zurücksetzen


von Belo L. (belo)


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

: Bearbeitet durch User
von Florian F. (flof3000)


Lesenswert?

Unterschied '\0' und "\0"?

von Can Fänger (Gast)


Lesenswert?

Peter L. schrieb:
> ich habe hier gelesen,

Lies lieber mal ein Lehrbuch zu C und lerne die Sprache richtig.

von Belo L. (belo)


Lesenswert?

danke, ne, ist kein Unterschied geht auch nicht mit '\0'.

von Belo L. (belo)


Lesenswert?

"Lies lieber mal ein Lehrbuch zu C "

ich wollte damit nur sagen, dass ich die Forumssuche schon bemüht habe. 
C-Bücher lese ich auch, aber da steht es genauso.

: Bearbeitet durch User
von R. M. (n_a_n)


Lesenswert?

0 = 0x00 <> '0'
kapiert ?

von Belo L. (belo)


Lesenswert?

ich verstehe schon. Und wo meinst du, dass ich NULL und '0' verwechsle?

: Bearbeitet durch User
von R. M. (n_a_n)


Lesenswert?

das bedeutet du solltest mal

  text[0] = 0x00;

schreiben.

von A. S. (Gast)


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).

von NurEinGast (Gast)


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.

von R. M. (n_a_n)


Lesenswert?

Das Zeichen '0' hat den Wert 0x30 !

von Belo L. (belo)


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

: Bearbeitet durch User
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Belo L. schrieb:
> Ich gebe den Sting aus und er ist unverändert

Zeig Deinen kompletten Quelltext. Da stimmt irgendwas nicht.

von Dirk B. (dirkb2)


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.

von Belo L. (belo)


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++;
        }
    }
}

von R. M. (n_a_n)


Lesenswert?

Belo L. schrieb:
> Ich gebe den Sting aus und er ist unverändert

hmm
1
  char text[81] = "Blablabla";
2
  printf("zuerst %s\n",text);
3
  text[0] = 0x00;
4
  printf("und nun %s\n",text);

verhält sich wie erwartet
der c -string wird mit 0 terminiert und nicht mehr gedruckt.

von Norbert (Gast)


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';

von NurEinGast (Gast)


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; )

von Belo L. (belo)


Lesenswert?

super, vielen Dank, das funktioniert!

Aber warum muss ich das machen ? Und ist das nur beim Arduino so ?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Belo L. schrieb:
> Ich gebe den Sting aus und er ist unverändert

Dann gibst du einen anderen String aus.

Oder du gibst einen Teilstring wie text+2 aus.

Oder du hast die Quelle nicht neu compiliert.

Und was soll überhaupt "String zurücksetzen" genau bedeuten?

von Belo L. (belo)


Lesenswert?

da sind einige Beiträge dazwischen gekommen. Also noch mal genauer, das 
funktioniert:

Ahhh, Arduino...
füge mal hinter
iii++;
eine Zeile ein
zeile[iii]='\0';

Aber warum ?

von NurEinGast (Gast)


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.

von Norbert (Gast)


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'

von Belo L. (belo)


Lesenswert?

Vielen, vielen Dank. Jetzt ist mir das endlich klar. Ist also zum Glück 
kein Arduino-Special.

von Norbert (Gast)


Lesenswert?

Belo L. schrieb:
> Ist also zum Glück kein Arduino-Special.

Nein, aber bei Arduino gehe ich immer erst mal von einem 
Einsteiger/einer Einsteigerin aus und erkläre die Dinge etwas einfacher. 
;-)

von Belo L. (belo)


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.

von Dumdi D. (dumdidum)


Lesenswert?

Belo L. schrieb:
> Macht ein "Profi" nichts mit Arduino ?

Korrekt.

von Belo L. (belo)


Lesenswert?

Ok, und warum nicht, sind doch ganz praktisch.

von Dirk B. (dirkb2)


Lesenswert?

Belo L. schrieb:
> Geht ja bei C schon in Richtung Assembler.

C ist eine einfache Sprache.
Das macht sie aber nicht einfach lernbar.

von A. S. (Gast)


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.

von Belo L. (belo)


Lesenswert?

danke.

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

Wird also als Fehler gewertet. Welche gibt es denn noch ?

: Bearbeitet durch User
von Mr. Y (Gast)


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;).

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Mr. Y schrieb:
> - Vergessen von break in switch.

Zumindest dafür kennt GCC inzwischen eine Warnung.

von Walter S. (avatar)


Lesenswert?

Belo L. schrieb:
> char text[80];
> text[0] = "\0";

da müsste auch eine Warnung kommen.
Vor allem als Anfänger sollte man Warnungen immer als Fehler ansehen

von Zeno (Gast)


Lesenswert?

Dumdi D. schrieb:
> Belo L. schrieb:
>> Macht ein "Profi" nichts mit Arduino ?
>
> Korrekt.

Wie war noch mal die Steigerung von arrogant?

von Frank M. (ukw) (Moderator) Benutzerseite


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.

von Mark B. (markbrandis)


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.

von Eric B. (beric)


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
}

: Bearbeitet durch User
von Belo L. (belo)


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.

von Rolf M. (rmagnus)


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.

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.