Hallo!!!
Bastele gerade an einem Prog. für eine Jalousiene-Steuerung mit
einem Arduino-Uno, Relaiskarte und 2x 8x8 MAX7219 Led-Matrix.
Auf den 2 Led-Matrix laufen die Kommunikationsinfos und andere
Werte, die als Laufschrift, Scrolltext ausgegeben werden.
Bei diesem Matrix-Code-Abschnitt stösse ich auf ein merkwürdiges
Verhalten von Zuweisung des Pointers auf ein String.
Nachdem die while Schleife abgearbeitet ist (wo ich einen einfachen
Scrolltext realisiere), möchte ich nach nächstem Loop vor der Schleife
den Pointer mit if Bedinguhn wieder auf dem Anfang vom String führen,
damit der Scrolltext immer wieder von neuem durchlauft.
Nun, habe ich im Code die Zeilen ausklammert dort wo dies nicht
funktioniert!
Der untere Code funktioniert so wie ich ihn poste, aber nicht mehr,wenn
sich
char* s=string; in den Zeilen 26 oder 48 befindet.
Warum ist es so, was mache ich denn falsch?
( die viele Serial.prints sind nur wegen Fehlersuche drin)
1
// Einzelne Char mit Pointer aus dem String auslesen
2
// Testprogramm 2015 Textscroll
3
//
4
charstring[]="<ABC321>";
5
intstringlaenge=strlen(string)+1;// +1 wegen Nullterminierung
6
intcounter=0;
7
char*s=string;// Pointer zeigt auf erste char im string
JoJoBa schrieb:> Serial.print(*s);
Das in *s stehende Zeichen wird als Adresse eines Strings interpretiert.
Soll das so? Und warum beachtest du keine Warnungen?
JoJoBa schrieb:> Warum ist es so, was mache ich denn falsch?
Variablen sind nur innerhalb des Blocks bekannt, in dem sie deklariert
wurden.
Blöcke sind die Bereiche, die zwischen '{' und '}' stehen.
@Gjlayde
Ich bekomme keine Warnungen, der sketch funzt eiwandfrei wenn
char* s=string;
sich im Loop vor der while-Schleife befindet.
Der Scrolltext wird in jedem Loop einmal durchgeführt.
Wenn sich aber
char* s=string; nach der while-Schleife eingefügt wird
oder davor im if...
dann bekomme ich NUR EINEN TEXTDURCLAUF.
deshalb verstehe ich dieses Verhalten nicht!!!???
@mfro
Du hast Recht, aber das ist hier gegeben!
Alle Wariablen sind global deklariert, vor dem setup!
....oder verstehe ich etwas nicht?
Gruß,csaba
Johann L. schrieb:> Das in *s stehende Zeichen wird als Adresse eines Strings interpretiert.
Nö. Damit wird der Inhalt einer Speicherstelle zurückgeliefert - also
ein Buchstabe/Zeichen.
STK500-Besitzer schrieb:> Johann L. schrieb:>> Das in *s stehende Zeichen wird als Adresse eines Strings interpretiert.>> Nö. Damit wird der Inhalt einer Speicherstelle zurückgeliefert - also> ein Buchstabe/Zeichen.
Genau. und dieser Buchstabe/Zeichen wird dann an eine FUnktion
übergeben, die die Adresse eines Strings haben will!
JoJoBa schrieb:> Du hast Recht, aber das ist hier gegeben!> Alle Wariablen sind global deklariert, vor dem setup!> ....oder verstehe ich etwas nicht?
Ja. Eine Deklaration einer Variable in einem "inneren" Block "überdeckt"
die gleichnamige Variable aus einem "äußeren" Block. Du hast dann halt
zwei Variablen gleichen Namens (das ist durchaus erlaubt), kannst aber
"innen" nur auf die innere zugreifen. Wird der Block verlassen,
verschwindet die "innere" Variable (und alles, was Du da reingeschrieben
hast).
1
char*s=string;
Deklariert (und initialisiert) eine (neue) Variable.
Wenn ich den Sketch ins Arduino UNO lade und den Seriellen Monitor
aktiviere, dann kann ich schön beobachten wie die einzelne
Buchstaben in der Reihe nach einzeln ausgegeben werden!
Genau das, was ich auch haben will.
Die while-Schleife tut was es soll und die *s tut auch was es soll!
Nun will ich in jedem Loopdurchlauf diesen Text im string
immer wieder von neuem durchführen.
Dazu muss ich vor der while-Schleife dem Pointer *s sagen,
dass er wiedermal auf die erste char im string zeigen soll.
Die klappt es dann wenn:
char* s=string; vor dem while vorkommt!
es klappt nicht, wenn
char* s=string; nach dem wheil eingefügt wird!
(hier wird while nur 1x ausgeführt und dann nicht mehr, so wie wenn
char* s=string; überhaupt nicht da wäre)
Und genau das ist für mich ein Rätsel, da ich später den
Befehl char* s=string; in eine if Bedingung packen muss!
Es wird benötigt für das weitere Programm, aber ich muss zuerst
diesen Sachverhalt klären, sonnst komme ich nicht weiter.
Studiere seit 2 wochen alles was ich über Pointer im web finde,
und da ich steckengeblieben bin, bitte ich um euere Hilfe
bei diesem Problem!
Danke vielmals!!!!
JoJoBa schrieb:> sketch
Sketch: ist eine kurze komödiantische Szene, die einer reduzierten
Handlung folgt und mit einer prägnanten Schlusspointe abschließt.
Okay, du hast uns erwischt!
damit erzeugst du die pointer-Variable s und weist ihr "gleichzeitig"
den Wert von string zu (etwas verkürzt geschrieben).
Wenn du diese beiden Befehle trennst, klappt es auch:
Johann L. schrieb:> Sketch: ist eine kurze komödiantische Szene, die einer reduzierten> Handlung folgt und mit einer prägnanten Schlusspointe abschließt.
oder eine Skizze...
JoJoBa schrieb:> Studiere seit 2 wochen alles was ich über Pointer im web finde,> und da ich steckengeblieben bin, bitte ich um euere Hilfe> bei diesem Problem!
Wie wärs wenn du erst mal ordentlich C++ lernen würdest mit einem Buch.
Damit sparst du dir eine Menge Frust.
JoJoBa schrieb:> Studiere seit 2 wochen alles was ich über Pointer im web finde,
Studier ruhig weiter, das wird dir später sicher nützlich sein. Dein
aktuelles Problem löst du so aber nicht, das hat nämlich mit Pointern
wenig zu tun.
Oliver
JoJoBa schrieb:> Der Scrolltext wird in jedem Loop einmal durchgeführt.
Soweit ich informiert bin, ist loop() mit dem main() eines Standard C
Programmes identisch. D.h., Deine neue Zuweisung an *s bringt nichts, da
loop() nach der while-Schleife beendet wird. Gemeint ist, dass loop()
terminiert und Dein AVR nichts mehr macht.
Nach einem Reset wird dann loop() wieder einmal ausgeführt.
Du solltest um die derzeitige while-Schleife noch eine zweite legen.
Etwa so:
1
while(1){// Dauerschleife....bis zum Reset oder neuem Programm flashen
Ich sehe, ich muss noch etwas Hintergrundinfo zu meinem Hilferuf
zufügen :) ;
Der Programmschnippsel soll später ohne DELAY laufen,damit die
anderen Aufgaben auch "gleichzeitig" bearbeitet werden.
Deshalb benütze ich in Weiterem dann millis() timing statt delay
und deshalb kann ich kein while mer verwenden sondern das if.....
Zurück zu meinem Problem;
Der if wird benötigt um beim erreichen der \0 Terminierung im
String wieder den Pointer *s auf den Anfang vom String zu setzen...
Dies wollte ich mit gepostetem Code zeigen (siehe Beitragsanfang)
hier; //if (*s != 0)//
(es ist noch ausgeklammert weil es nicht funktioniert hat)
Darf ich die Hilfestellung also auch so formulieren;
Wie sollte der Codebeispiel aussehen, damit mein Vorhaben ohne delay,
also ohne while aber mit if Bedingung alle x sekunden den
Beispieltext Buchstabenweise immerwieder ausgibt.
Nun ich bin über 50 und C Programmierung lerne ich im Eigenstudium
seit einem Jahr, weil es mir mega Spass macht und will euere Zeit
nicht damit rauben, mir fertige Lösungen zu liefern.
Stolpere ich aber gerade über ein Steinchen, wo ich selber nicht
weiter weiß :-(
@STK500-Besitzer
habe gerade Dein Vorschlag probiert, es klappt aber leider noch nicht...
@ OldMan
Danke Dir für das Beispiel.
void loop() {
....tu was
}
wird ziklisch immer wieder ausgeführt, ist ja eine Schleife.
Bitte beachte; Der Code lauft eiwandfrei, der Text im String
wird Buchstabenweise auf dem Serial Monitor ausgegeben!
dieses Verhalten ändert sich auf-> Text wird nur 1Mal rotiert
wenn sich char* s=string;
in der Zeile im void loop() hinter der while-Schleife plaziert wird!
(@STK500-Besitzer sein Vorschlag mit
char* s;
s=string; habe auch probiert)
Hätte ich probleme mit dem char* s=string; dann
dürfte das Programm nicht laufen.
Es tut es aber, wenn sich char* s=string;
in eine Zeile vor dem while eingefügt wird !?
Ja, ja. Arduino schafft Probleme, die wir ohne es nicht hätten.
Scheussliches Zeug!
Die Funktion "loop" wird endlos immer wieder aufgerufen.
Siehe:
http://forum.arduino.cc/index.php?PHPSESSID=4298fmuetk14gba8sbbfskkk31&topic=45911.msg333093#msg333093
Das ist kein C-Schlüsselwort, wie etwa "while" oder "for".
Ohne Gewähr! Offen gesagt, will ich es so genau denn auch wieder nicht
wissen.
Dann ist das ein C-Problem. An dieser Stelle kann man nur wieder mal von
Arduino abraten. Das ist die P... im A...
Wenn Du wiederholt oder auch an verschiedenen Stellen im Code der loop
Funktion die "Deklaration" mit "Initialisierung" hinsetzt, dann
überdeckt diese Deklaration alle in den jeweils äusseren "Blöcken"
deklarierten gleichnamigen Variablen.
D.h. Wenn Du ein zweites Mal in die Funktion loop eintrittst, dann sind
alle Deine Wertveränderungen von Variablen, die innerhalb von loop
erfolgen, verloren.
Das Programm verfolgt insofern auch den korrekten Ansatz, char s
zunächst ausserhalb jeder Funktion zu deklarieren.
Mit den nachfolgenden Deklarationen aber, überdeckst Du, wie schon (und
nicht nur von mir) erwähnt die äusserste Deklaration. Das sind ganz
andere Variablen.
Also: Gleich C lernen und den ganzen Arduino-Plumpaquatsch jemandem
schenken, dem Du zwar das Schlechteste wünschst, aber wozu Dir nichts
Besseres einfällt.
Das muss ich in dem Zusammenhang präziser sagen:
D.h. Wenn Du ein zweites Mal in die Funktion loop eintrittst, dann sind
alle Deine Wertveränderungen von Variablen, die innerhalb von loop
erfolgen, und die innerhalb der Funktion deklariert sind verloren.
@KLAUS
>Das Programm verfolgt insofern auch den korrekten Ansatz, char s
zunächst ausserhalb jeder Funktion zu deklarieren.
Mit den nachfolgenden Deklarationen aber, überdeckst Du, wie schon (und
nicht nur von mir) erwähnt die äusserste Deklaration. Das sind ganz
andere Variablen.<
OK, ich werde es reinziehen....
Wie würde es "richtig" aussehen, bzw. wie soll ich dann
folgendes realisieren;
1
if(stringlaenge==1){
2
Serial.println(" Stringlaenge wird neu ermittelt------------------------ ");
3
char*s=string;
4
stringlaenge=strlen(string)+1;
5
}
...ich möchte damit dem Programm folgendes sagen;
wenn die stringlänge erreicht ist,
setze den *s Pointer auf dem 1.char im string!
...damit der nächste while das gleiche macht wie bisher beim ersten
durchlauf.
und das klappt so nicht!? wie dann?
Gruß!
Liebe programmierer Freunde!
ich wage Jetzt einen neuen Ansatz um mir Hilfe zu holen.
Den bisherigen Code habe ich eingefügt um zu zeigen in welchen
Schwierigkeiten ich mich bei einem neuem Programm befinde.
Leider bin ich auf diese Weise nicht weitergekommen, deshalb poste ich
hier die Version, die bei mir in Einsatz kommen soll.
Der Code lauft auf einem Arduino-Uno und ich nutze die IDE 1.5.8
bzw.1.6.4
Im Code ist ein String mit einem Text definiert.Der Text wird
Buchstabenweise nacheinander auf dem IDE serial Monitor -alle 2 sekunden
die nächste Buchstabe, ausgegeben.
Soweit-sogut, dies funktioniert am Anfang
(1x Text Buchstabenweise anzeigen)tadellos.
Nacdem aber der *s Pointer die \0 Terminierung erreicht hat,
zeigt er mir nicht mehr wieder auf die 1.Buchstabe im Text.
obwohl ich versuche dies neu zuzuweisen mit :
char* s=string;
dieser Ausschnitt hat dann keine wirkung:
1
if(stringlaenge==1){
2
Serial.println(" Stringlaenge wird neu ermittelt------------------------ ");
3
char*s=string;// Zeige auf den ersten char im string
4
stringlaenge=strlen(string)+1;
5
}
Was mache ich hier falsch, bzw wie schreibe ich es richtig?
Über eine richtige Lösung wäre ich sehr erfreut!
Weiter Oben in den Hilfeansätzen von Teilnehmer wurden auf verschiedene
Dinge hingewiesen, die alle konnte ich aber noch nicht erfolgreich
verwenden.
hier ist mein Code:
1
// Einzelne Char mit Pointer aus dem String auslesen
2
// Testprogramm 2015 ohne DELAY
3
//
4
unsignedlongzeitstempel;// Variable um den aktuellen Zeitwert zu speichern
5
unsignedlongdisplaychar;
6
intzeitfenster=2000;// 2 sec
7
8
charstring[]="<ABC321>";
9
intstringlaenge=strlen(string)+1;// +1 wegen Nullterminierung
10
char*s=string;// Pointer zeigt auf erste char im string
laß' das "char *" vor "s=..." im inneren Block einfach weg. Damit ist
das keine Deklaration mehr, sondern eine simple Zuweisung an die global
definierte Variable.
Und kaum macht man's richtig, schon geht's...
...und kauf dir endlich ein C-Buch, oder auch dir ein Tutorial im Netz.
Mit Trail and Error wird das nichts, wie man an deinen Beiträgen
erkennt. Du hast dein Problem bisher nicht mal ansatzweise verstanden.
Im Kapitel deiner Wahl im C-Buch sollte was zum den Gültigkeitsbereich
(oder englisch:Scope) von Variablen stehen.
Oliver
Bauteiltöter schrieb:> STK500-Besitzer schrieb:>> Johann L. schrieb:>>> Das in *s stehende Zeichen wird als Adresse eines Strings interpretiert.>>>> Nö. Damit wird der Inhalt einer Speicherstelle zurückgeliefert - also>> ein Buchstabe/Zeichen.>> Genau. und dieser Buchstabe/Zeichen wird dann an eine FUnktion> übergeben, die die Adresse eines Strings haben will!
Ok, ich muss mich korrigieren. Es geht ja nicht um C, sondern um C++.
Serial.print() gibt es 4x, eine Version für int, eine für float, eine
für char und eine für char*.
das serial.print(*s) ist also korrekt und wird auch keine Warnung
erzeugen.
@mfro
....mensch Markus, Du hast mir am Anfang die Lösung verraten,
ich habe es aber nicht richtig interpretiert.....
DANKE für den Hinweis, ich verstehe jetzt zwar noch
immer nicht ganz, aber die Lösung ist wie Du sagst!
ich darf es nicht immer wieder neu Deklarieren!!!
in der Zwischenzeit habe ich mein Problem auf andere weise mit
Feldindizes gelöst, das will ich aber nicht einsetzen.
In meinem Selbststudium bin ich seit 2 Wo bei den Pointers
strings und arrays angelangt und erst jetzt habe angefangen
verschiedene Aufgaben lösen zu wollen....
und bin bei diesem Stolperstein stehengeblieben.
Danke auch für andere schlaue Vorschläge mit Büchern und sooo,
aber das ist längst im Gange, nur halt über 50 rattert ja die
Festplatte nicht so mit 15000rpm :-)....wie früher
möchte trozdem noch hier die andere Variante posten, vielleicht
hilft es doch jemanden anderen....
Markus, vielen Dank für den richtigen Hinweis!!!!
>> Man kommt nicht durch Wollen,Hoffen,Wünschen voran, sondern durch
Absichten <<
Gruß, csaba und DANKE euch ALLEN!
Sorry, aber eine Verständnissfrage bleibt mir immer noch;
Am Anfang habe ich den Code mit while Schleife gepostet
und auf mein Problem hingewiesen.
In dem main Loop gibt es die zeile mit dem Pointer:
char* s=string;
danach
while Schleife
danach
kehre zurück zum loop Anfang,
und diese Reihenfolge funktioniert reibungslos!
Ändere ich im main loop die Anweisungen so, dass ;
while-Schleife
danach
char* s=string;
danach
ende vom loop, kehre zurück zum Anfang
dann habe ich nur 1xTextdurchlauf, und dann ist schluss.
Der Loop schleift weiter um sich hin ohne die Buchstaben auszugeben.
Warum kommt es zu diesem Verhalten?
Und seit 2 Wochen recherchiere ich im web über Pointer und
Tausende andere Dinge, aber fand bisher keine Erklärung.
die angeblich wiederholte Deklaration
char* s=string;
kommt in beiden Codevarianten gleich vor!
Gruß!
JoJoBa schrieb:> DANKE für den Hinweis, ich verstehe jetzt zwar noch> immer nicht ganz, aber die Lösung ist wie Du sagst!
Was ist denn unklar? Ist doch eigentlich ganz einfach:
1
if(stringlaenge==1){
2
Serial.println(" Stringlaenge wird neu ermittelt------------------------ ");
3
char*s=string;// Zeige auf den ersten char im string
4
stringlaenge=strlen(string)+1;
5
}
Du erzeugst in diesem if-Block eine Variable namens s. Nach dem Ende des
Blocks hört diese Variable auf zu existieren. Und diese Variable hat
nichts, aber auch gar nichts mit dem s zu tun, das du am Anfang des
Programms definierst. Es sind zwei komplett separate Variablen.
Das s, das du hier verwendest, ist allerdings das global definierte s:
1
if((zeitstempel-displaychar)>=zeitfenster)
2
{
3
if(*s!=0)// solange die Nullterminierung am Ende vom string erreicht wird...
@rmagnus
Ok, ich glaub ich kapiere es jetzt!
Die Variable mit dem Typ char habe ich am Anfang deklariert
und auch Initialisiert als global!
..damit überall im Code verwendbar wird.
In der if....Anweisung habe sie aber wieder
deklariert und initialisiert.
Dabei war die Deklaration hier falsch;
ich muss sie nur neu Initialisieren, damit sie (die Gleiche!)
mir als Pointer auf den ersten char im string zeigt!
ich Verstehe es jetzt!
Suuuper, DANKE!!!!
@ JoJoBa
Da die meisten hier diesen Punkt mehr oder weniger sofort gesehen haben,
eine Deklaration mitten im Code ist eher ungewöhnlich -, kannst Du davon
ausgehen, dass das eine grundlegende Sache ist. (Es sei zugegeben, dass
auch dazu eine gewisse Praxis gehört).
Dazu solltest Du einfach mal ein C-Buch lesen. Und dann noch lernen,
worin bei Arduino die Besonderheiten bestehen, aufgrund deren Du anders
vorgehen muss als "der Rest der Welt".
Ein Debugger wäre gut.
Übrigens hättest Du Dir im AVR-Studio im Simulator das genaue Problem
einmal anschauen können.
Na ja. Noch ist es nicht zu spät. :-)
@Klaus,
Du sprichst natürlich die Schokoladenseite an....
ich stecke erst beim Arduino IDE und studiere die
pdf. fach-Geschenke aus dem web mit mal kleinerem mal größerem
Erfolg.
Neben einem Beruf ist diese Tätigkeit mein Hobby geworden
aber ich will nicht aufgeben, und befor mich die Frustration
packen würde, greife ich zum Internetportal, wie dieser hier...
Es kann sein dass ich damit einige Leuchte abschrecke, oder gar
verärgere, aber das ist natürlich nicht mein Absicht!
Möchte auf jedem Fall die Hilfebereitschaft von euch Allen loben,
und wünsche Jedem weiterhin viel Erfolg!!!!
Gruß,
csaba