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
Peter L. schrieb: > ich habe hier gelesen, Lies lieber mal ein Lehrbuch zu C und lerne die Sprache richtig.
"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
ich verstehe schon. Und wo meinst du, dass ich NULL und '0' verwechsle?
:
Bearbeitet durch User
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).
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.
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
Belo L. schrieb: > Ich gebe den Sting aus und er ist unverändert Zeig Deinen kompletten Quelltext. Da stimmt irgendwas nicht.
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.
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++; } } }
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.
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'; |
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; )
super, vielen Dank, das funktioniert! Aber warum muss ich das machen ? Und ist das nur beim Arduino so ?
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?
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 ?
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.
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'
Vielen, vielen Dank. Jetzt ist mir das endlich klar. Ist also zum Glück kein Arduino-Special.
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. ;-)
"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.
Belo L. schrieb: > Geht ja bei C schon in Richtung Assembler. C ist eine einfache Sprache. Das macht sie aber nicht einfach lernbar.
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.
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
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;).
Mr. Y schrieb: > - Vergessen von break in switch. Zumindest dafür kennt GCC inzwischen eine Warnung.
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
Dumdi D. schrieb: > Belo L. schrieb: >> Macht ein "Profi" nichts mit Arduino ? > > Korrekt. Wie war noch mal die Steigerung von arrogant?
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.
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.
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
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.