Forum: Compiler & IDEs char * Verkettung von Arrays Chars


von Andreas F. (codecasa)


Lesenswert?

Warum funktioniert das nicht ich habe folgenden Code:
  adrIP++;
  for (int iP=0; iP<anzCMD; iP++)
  {
    for (unsigned int t=0; t<sizeof(cmdP); t++)
    {
      *((char*)&CMD[iP] + t) = EEPROM.read(adrIP + (iP * sizeof(cmdP)) 
+t);
    }

     //char *p1;
     //itoa(CMD[iP].param1,p1,10);

     char *strTemp;

                   if (CMD[iP].Befehl == CMD_ZEIT)
                   {
                      char strKA = '(';
                      strTemp = strCMD[CMD_ZEIT] + strKA;
                      //strcat(strTemp, "oko");
                   }

                   else if (CMD[iP].Befehl == CMD_PMP)
                   {
                      strTemp = strCMD[CMD_PMP];
                   }
                   else if (CMD[iP].Befehl == CMD_SAN)
                   {
                      strTemp = strCMD[CMD_SAN];
                   }
                   else if (CMD[iP].Befehl == CMD_START_IMP)
                   {
                      strTemp = strCMD[CMD_START_IMP];
                   }
                   else if (CMD[iP].Befehl == CMD_STOP_IMP)
                   {
                      strTemp = strCMD[CMD_STOP_IMP];
                   }
                   else if (CMD[iP].Befehl == CMD_END)
                   {
                      strTemp = strCMD[CMD_END];
                   }


           mnuAddCMD(strTemp);


      Serial.println(strTemp);


Der mischt ständig Adreessen sieht einer den Fehler?

von Krapao (Gast)


Lesenswert?

>           mnuAddCMD(strTemp);

Spätestens in dieser Zeile sollte dein Compiler eine Warnung werfen, 
dass du möglicherweise eine nicht initialisierte Variable benutzt. Das 
kann zur Laufzeit durchaus dazu führen, dass dir unerwartete Werte 
angezeigt werden.

Beim Debuggen würde ich als erstes nachsehen, ob aus dem EEPROM sauber 
nach CMD kopiert wurde.

von Andreas F. (codecasa)


Lesenswert?

Es kommt keine Warnung

Und debugen kann ich auch nicht hab die IDE von ARDUINO

von Krapao (Gast)


Lesenswert?

Oh, stumpfe und fehlende Werkzeuge. Dann bist du als Anfänger ziemlich 
aufgeschmissen.

Die c't hatte letztens einen Artikel, wie man Arduino Programme 
innerhalb von AVR-Studio entwickeln kann. Dort hättest du zusätzlich 
einen Simulator.

Nur mit der Arduino-IDE ist es nicht unmöglich zu debuggen. Du brauchst 
halt Ideen und ein gutes Verständnis von C++ und C. Früher hat man dazu 
den Code zeilenweise mit printf (Serial.println()) gespickt und das 
Programm halt entsprechend oft ausgeführt bis man irgendwann den Bug 
umzingelt hat.

Du kannst auch dein komplettes Projekt zeigen oder wenigstens ein 
repräsentativen Komplettcode mit dem Fehler. Vielleicht erbarmt sich 
jemand und entwanzt für dich.

von Krapao (Gast)


Lesenswert?


von Stefan E. (sternst)


Lesenswert?

Andreas Frauenstein schrieb:
> mischt ständig Adreessen

Was genau bedeutet das?
Wie sehen die Deklarationen/Definitionen der beteiligten Variablen aus?


1
     char *strTemp;
2
...
3
                      char strKA = '(';
4
                      strTemp = strCMD[CMD_ZEIT] + strKA;
Was soll das darstellen? Ich hoffe du denkst nicht, so an den String ein 
Zeichen anhängen zu können.

von Andreas F. (codecasa)


Angehängte Dateien:

Lesenswert?

AVR -Studio hätte ich auch gerne aber ich nutze Linux !

Ich würde lieber mit VIM von Linux Programmieren und dann mit makefile 
etc hatte ich aufm anderen rechner schon laufen.

für eclipse habe ich jetzt auch nicht mehr die zeit einzurichten.

Der Code ist im Anhang

Jetzt geht es nur im LCD Zeigt der nur die Letzte Zeilen wiederholt an 
an

Ich denke der Hängt sich auf wegen speichermangel und zwar beim addMenu

von Krapao (Gast)


Lesenswert?

Untersuche dein Programm mal mit avr-size. Das ist bei der Arduino-IDE 
dabei und kann von der Konsole aus aufgerufen werden.
http://www.mikrocontroller.net/articles/AVR-GCC#Tipps_.26_Tricks

Oder specke ab und prüfe deine Hypothese.

Ich kann beides nicht, weil fürs Übersetzen deines Quellcodes 
essentielle Dateien fehlen.

von Karl H. (kbuchegg)


Lesenswert?

Andreas Frauenstein schrieb:

> Der mischt ständig Adreessen sieht einer den Fehler?

Ich denke, ich weiß was du damit meinst.

Dein Problem ist, dass dir nicht klar ist, dass du mit einem Pointer 
lediglich einen Verweis auf einen Speicher hast.

Wenn du hier
           mnuAddCMD(strTemp);
aufrufst, dann bindest du NICHT einen Text an einen Menüpunkt. Du 
bindest lediglich eine Adresse an diesen Menüpunkt! Benutzen aber alle 
Menüpunkte dieselbe Adresse, dann zeigen die auch alle denselben Text 
an. Nämlich den, von dem du ihnen die Adresse gegegen hast. Veränderst 
du den eigentlichen Text, dann zeigen auch alle Menüpunkte den 
veränderten Text an.

Ein Beispiel

  char TestString[10];

  strcpy( TestString, "Juhu" );

  char* Str1 = TestString;
  char* Str2 = TestString;


das hier hat dieses gebaut

  Str1
  +------+
  |  o-------------+
  +------+         |
                   |   +---+---+---+---+---+---+---+---+---+---+
                   +-->| J | u | h | u | \0|   |   |   |   |   |
                +----->+---+---+---+---+---+---+---+---+---+---+
                |
  Str2          |
  +-----+       |
  |  o----------+
  +-----+

2 Zeiger zeigen auf den gleichen String. Gibst du beide aus

   Serial.println( Str1 );
   Serial.println( Str2 );

Du siehst 2 mal "Juhu" auf der Ausgabe


veränderst du den eigentlichen String, egal wie, zum Beispiel

  strcpy( TestString, "Hallo" );
oder
  strcpy( Str1, "Hallo" );
oder
  strcpy( Str2, "Hallo" );

dann änderst du den String


  Str1
  +------+
  |  o-------------+
  +------+         |
                   |   +---+---+---+---+---+---+---+---+---+---+
                   +-->| H | a | l | l | o | \0|   |   |   |   |
                +----->+---+---+---+---+---+---+---+---+---+---+
                |
  Str2          |
  +-----+       |
  |  o----------+
  +-----+

aber nach wie vor zeigen beide Pointer auf den gleichen String. Eine 
Ausgabe


   Serial.println( Str1 );
   Serial.println( Str2 );

Wird daher 2 mal "Hallo" auf die Ausgabe zaubern. Und zwar egal, auf 
welchem Weg du den eigentlichen String änderst.

1
  char TestString[10];
2
3
  strcpy( TestString, "Juhu" );
4
5
  char* Str1 = TestString;
6
  char* Str2 = TestString;
7
8
  strcpy( TestString, "Hallo" );
9
  Serial.println( Str1 );

Die Ausgabe lautet "Hallo" und nicht mehr länger "Juhu", auch dann wenn 
das im Programmtext nicht mehr so einfach zu sehen ist. Denn die 
'Zuweisung' (mittels strcpy) an TestString hat für den Unbedraften ja 
nichts mit Str1 zu tun. Tatsächlich wurde aber durch die Art und Weise, 
wie der Pointer eingereichtet wurde erreicht, dass beide, Array und 
Pointer, aus Sicht der Stringverarbeitung denselben Speicher benennen 
(siehe ASCII Grafik).

Du musst also ein wenig vorsichtig sein. Nur weil du einen Pointer hast, 
heißt das nicht, dass du einen String hast, mit dem du fuhrwerken 
kannst, wie du gerade lustig bist.

Und wenn dir nicht klar ist, was du eigentlich tust, dann fang an dir 
die Dinge auf einem Zettel aufzumalen, so wie ich das mit den 3 
Variablen gemacht habe. Das hilft!

von Andreas F. (codecasa)


Lesenswert?

Ja das ist mir schon klar aber mit
strcpy(strTemp, strCMD[CMD_PMP]);

schreibe ich doch den Inhalt von strCMD[CMD_PMP] an die strTemp

Bei der Ausgabe in Serial:
          mnuAddCMD(strTemp);


      Serial.print(an-1);
      Serial.print(":");
      Serial.print(iP);
      Serial.print(" :  ");
      Serial.print(CMD[iP].Befehl);
      Serial.print(":");
      Serial.print(strTemp);


Gibt er mir die Unterschiedlichen <strTemp> aus
Da Fuktioniert es doch beim menu hizufügen mnuAddCMD(strTemp);
hat er noch den alten wert: es ist für mich ein Rätsel ich dacht ich 
habe das mit den Pointern langsam verstanden.

von Krapao (Gast)


Lesenswert?

> Mit strcpy(strTemp, strCMD[CMD_PMP]);
> schreibe ich doch den Inhalt von strCMD[CMD_PMP] an die strTemp

In mnuAddCMD weist du newMenu->name einen Pointer auf char zu, d.h. die 
Adresse eines Strings, genauer des globalen strTemp Arrays (Aufruf ist 
ja mnuAddCMD(strTemp)).
1
void mnuAddCMD(char *n)
2
{
3
  Menu* newMenu = allocateMenu();
4
5
  if( newMenu == NULL )  
6
  {
7
    // da ist wohl was schief gelaufen
8
    Serial.println("newMenu = NULL");
9
    return;
10
  }
11
  newMenu->name = n; 
12
    
13
  Item11.addChild(*newMenu);
14
}

Möglicherweise fehlt hier schon eine Kopieraktion des Inhalts, was ich 
aber nicht ermitteln kann, weil Code fehlt (Wie ist die Struktur Menu 
definiert?).

Zurück zu Pointer auf char: Weil du in der Sourceversion im Attachment 
eine globales strTemp Array hast, ist das auch immer die gleiche 
Adresse.

Wenn jetzt die addChild() nicht kopiert sondern nur die Adresse 
weitergibt (was ich auch nicht ermitteln kann, weil Code fehlt), änderst 
du mit weiteren Kopieraktionen nach strTemp auch das worauf 
vorhergehende newMenu->name zeigen.

von Krapao (Gast)


Lesenswert?

Ich meine jetzt nicht, dass du auf Teufel komm raus strcpys machen 
musst. Du hast im Code feste Menütexte und man kann die Pointer darauf 
auch in die Menüstruktur weitergeben. Bloss man kann keine Vorschlag 
machen, wie das richtig funktionieren würde, wenn essentielle Codeteile 
nicht gezeigt werden.

von Andreas F. (codecasa)


Angehängte Dateien:

Lesenswert?

Krapao schrieb:
> In mnuAddCMD weist du newMenu->name einen Pointer auf char zu, d.h. die
> Adresse eines Strings, genauer des globalen strTemp Arrays (Aufruf ist
> ja mnuAddCMD(strTemp)).
>
>
1
> void mnuAddCMD(char *n)
2
> {
3
>   Menu* newMenu = allocateMenu();
4
> 
5
>   if( newMenu == NULL )
6
>   {
7
>     // da ist wohl was schief gelaufen
8
>     Serial.println("newMenu = NULL");
9
>     return;
10
>   }
11
>   newMenu->name = n;
12
> 
13
>   Item11.addChild(*newMenu);
14
> }
15
>
>
> Möglicherweise fehlt hier schon eine Kopieraktion des Inhalts, was ich
> aber nicht ermitteln kann, weil Code fehlt (Wie ist die Struktur Menu
> definiert?).

Die Menu.h befindet sich im Anhang

> Zurück zu Pointer auf char: Weil du in der Sourceversion im Attachment
> eine globales strTemp Array hast, ist das auch immer *die gleiche*
> Adresse.

Wieso wird mir dann von der Ausgabe: Serial.println(strTemp); 
unterschiedliche Werte angezeigt, aber Die Menüs bleiben bei dem letzten 
char * ?

> Wenn jetzt die addChild() nicht kopiert sondern nur die Adresse
> weitergibt (was ich auch nicht ermitteln kann, weil Code fehlt), änderst
> du mit weiteren Kopieraktionen nach strTemp auch das worauf
> vorhergehende newMenu->name zeigen.

wie gesagt den Code habe ich oben angehämgt und Die Menu.h befindet sich 
in diesem Anhang !

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Andreas Frauenstein schrieb:
> Wieso wird mir dann von der Ausgabe: Serial.println(strTemp);
> unterschiedliche Werte angezeigt, aber Die Menüs bleiben bei dem letzten
> char * ?

Was passiert wohl wenn du mit jemandem Telefonierst und jeden Satz auf 
eine Tafel schreibst, den Vorherigen aber immer wieder wegwischt?

Klar dein Gesprächspartner kriegt alles mit aber als Telefonprotokoll 
taugt's nix.

von Andreas F. (codecasa)


Lesenswert?

Hat den keiner eine Lösung Ich bin am verzweifeln :(

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Lies ein C-Buch, dort insbesondere das, was über Arrays, Pointer und 
Strings steht.

Empfehlenswert: Brian Kernighan & Dennis Ritchie, "Programmieren in C", 
2. Ausgabe, Hanser-Verlag. Kennt zwar kein C-99, aber das, was Du hier 
noch lernen musst, ist so grundlegend, daß diese Unterschiede irrelevant 
sind.

"Denn" schreibt man übrigens immer noch mit zwei "n".

von Karl H. (kbuchegg)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Lies ein C-Buch, dort insbesondere das, was über Arrays, Pointer und
> Strings steht.

Und dann erst mal ein paar Tage am PC üben.

Ach und noch was:
Die Ausschnitte, die bisher gezeigt wurden, sehen zumindest für mich 
nicht sehr Vertrauen erweckend aus. Ich denke, da stecken noch jede 
Menge anderer Probleme drinnen.
Daher: Wenn du mit deinen Studien am PC fertig bist und das erste 
Drittel des Kernighan&Richtie durch-gearbeitet (nicht nur duchgelesen!) 
hast, dann fang nochmal von vorne an. Mit mehr Wissen und mehr 
Sicherheit bei dem was du tust, wird dann auch das Ergebnis entsprechend 
besser. Kleb nicht daran, einen verkorksten Ansatz auf Biegen und 
Brechen retten zu wollen. Da braucht man schon viel Erfahrung um sowas 
durchzuziehen.

Wenn ich da grundlegend helfen sollte, würde ich wahrscheinlich genau 
das gleiche machen: wegwerfen und neu schreiben.

von Krapao (Gast)


Lesenswert?

> Hat den keiner eine Lösung Ich bin am verzweifeln :(

Und ich habe quasi aufgegeben.

Es sind inzwischen drei Sourcen zu beachten: lokale char * Version, 
globale char [] Version und Version mit Debugausgabe per Serial.print.

Von der ersten Version kennen wir eine unvollständige Funktion.

Von der zweiten erbettelten Version kennen wir die Hauptdatei und auf 
weiteres Betteln hin einen Teil der Menu-Library.

Von der Debugversion kennen wir ein Fragment von sieben Codezeilen.

Es wurde darauf hingewiesen, dass man mit dem unvollständigen Code 
eigentlich nur am raten ist.

Man hat auf Codevarianten einzugehen, die zu einem Fehler führen 
könnten, statt dass man sich die Codevariante ansehen kann, die 
tatsächlich benutzt wird.

Und man arbeitet mit deinen dünnen Fehlerbeschreibungen und fehlenden 
Debugausgaben.

Weil ein übersetzbarer Komplettcode fehlt, kann man sich den 
eigentlichen Fehler oder eine sinnvolle Debugausgabe auch nicht 
simulieren.

OK, es kam mit einem Teil der Menu-Library weiterer Code. Aber was ist 
die erste Anweisung im neuen Code: Ein Include einer weiteren 
unbekannten, lokalen Datei.

Letzter Tip und hier hat dein letzter Anhang geholfen, d.h. der Blick in 
den tatsächlichen Teilcode:

Die globale char [] Version ist für diese Menu-Library ungeeignet.

Es gilt mit dieser Version, wie Rufus so schön schreibt, "Was passiert 
wohl wenn du mit jemandem Telefonierst und jeden Satz auf eine Tafel 
schreibst, den Vorherigen aber immer wieder wegwischt?".

Denn das machst du, Schreiben (menu->name = n (= strTemp)) und danach 
Wegwischen (nachstes strcpy(strTemp,...)).

von Andreas F. (codecasa)


Lesenswert?

Krapao schrieb:

> Es gilt mit dieser Version, wie Rufus so schön schreibt, "Was passiert
> wohl wenn du mit jemandem Telefonierst und jeden Satz auf eine Tafel
> schreibst, den Vorherigen aber immer wieder wegwischt?".
>
> Denn das machst du, Schreiben (menu->name = n (= strTemp)) und danach
> Wegwischen (nachstes strcpy(strTemp,...)).


Aber newMenu->name = n; also newMenu wird von Menu* newMenu = 
allocateMenu bezogen !

Wenn du genau hinsiehst, übergibt allocateMenu() jedesmal wenn usedMnu++ 
das Feld inkrementiert eine andere Adressse oder Irre ich mich ?

Also ist newMenu jedesmal ein Zeiger auf eine andere Menu-Adresse

Menu* allocateMenu()
{
  if( usedMnu >= 20 ) return NULL;
  return &mnuProg[usedMnu++];
}


void mnuAddCMD(char *n)
{
  Menu* newMenu = allocateMenu();

  if( newMenu == NULL )
  {
    // da ist wohl was schief gelaufen
    Serial.println("newMenu = NULL");
    return;
  }

  newMenu->name = n;


  Item11.addChild(*newMenu);
}

von Krapao (Gast)


Lesenswert?

> Aber newMenu->name = n; also newMenu wird von Menu* newMenu =
> allocateMenu bezogen !

Das ist richtig aber unerheblich. Es nutzt nix, wenn du jedes Mal eine 
neue Tafel besorgst. Dann drauf schreibst und dann die neue Tafel 
auswischst.

von Andreas F. (codecasa)


Lesenswert?

Krapao schrieb:
>> Aber newMenu->name = n; also newMenu wird von Menu* newMenu =
>> allocateMenu bezogen !
>
> Das ist richtig aber unerheblich. Es nutzt nix, wenn du jedes Mal eine
> neue Tafel besorgst. Dann drauf schreibst und dann die neue Tafel
> auswischst.

Okay wieso funktioniert es jetzt Ohne das Ich was an der allocateMenu() 
oder cmdAddMenu ändere mit folgendem code?


  int an = 0;
  for (int iP=0; iP<anzCMD; iP++)
  {

  char *strTemp;


                   if (CMD[iP].Befehl == CMD_ZEIT)
                   {
                      strTemp = "zeit";
                      an++;
                   }

                   else if (CMD[iP].Befehl == CMD_PMP)
                   {
                      strTemp = "pmp";
                   }
                   else if (CMD[iP].Befehl == CMD_SAN)
                   {
                      strTemp = "san";
                   }
                   else if (CMD[iP].Befehl == CMD_START_IMP)
                   {
                      strTemp = "imp_start";
                   }
                   else if (CMD[iP].Befehl == CMD_STOP_IMP)
                   {
                      strTemp = "imp_stop";
                   }
                   else if (CMD[iP].Befehl == CMD_END)
                   {
                      strTemp = "end;";
                   }



      mnuAddCMD(strTemp);

      Serial.print(an-1);
      Serial.print(":");
      Serial.print(iP);
       Serial.print(":");
      Serial.print(strTemp);
      Serial.println("");


   }


    Root.goMenu(Item11);

von Krapao (Gast)


Lesenswert?

Das "Auswischen" ist bei der global char [] Version:

Alle deine newMenu->name haben den gleichen Inhalt: Den einen Zeiger auf 
den Inhalt von strTemp.

Und wenn du jetzt den Inhalt von strTemp z.B. durch ein strcpy() 
änderst, zeigen alle name Variablen in allen Menu Objekten auf den 
geänderten Inhalt.

von Krapao (Gast)


Lesenswert?

> Okay wieso funktioniert es jetzt Ohne das Ich was an der allocateMenu()
> oder cmdAddMenu ändere mit folgendem code?

Darauf hatte ich dich oben schon hingewiesen:

>> Die globale char [] Version ist für diese Menu-Library ungeeignet.

von Andreas F. (codecasa)


Lesenswert?

Ja stimmt das geht dan immer tiefer und alle voranhgestellten 
newMenu.name haben dann die Adresse vom Letzten strTemp.

Jetzt schnall ich es endlich.


Jetzt habe ich aber noch das Problem das der Folgende Code soweit 
funktioniert aber sobalt ich im diplay bis zur letzten lcd Zeile 
runterscrolle kommen wieder andere Adressbereiche

                   if (CMD[iP].Befehl == CMD_ZEIT)
                   {
                      char strA[20];
                      strcpy(strA, "zeit");
                      strcat(strA, "(50);"); // hier sollen dan später 
CMD[iP].param1 rein

                      strTemp = strA;

                      an++;
                   }

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Andreas Frauenstein schrieb:
> strTemp = strA;

Du hast immer noch nicht im C-Buch nachgelesen, oder sonstwie 
herausgefunden, was diese Zeile macht. Oder?

von Krapao (Gast)


Lesenswert?

Schau dir im C-Buch die Gültikeitsbereiche von lokalen Variablen an. 
Übertrage dein Wissen dann auf die Variable strA: Worauf zeigt strTemp 
nach dem letzten gezeigten }? Richtig, auf ungültigen Speicher.

von Andreas F. (codecasa)


Lesenswert?

Krapao schrieb:
> Schau dir im C-Buch die Gültikeitsbereiche von lokalen Variablen an.
> Übertrage dein Wissen dann auf die Variable strA: Worauf zeigt strTemp
> nach dem letzten gezeigten }? Richtig, auf ungültigen Speicher.

Ja weil die Var in den Klammern deklariert wird hab sie jetzt am Anfang 
von der Forschleife.

von Andreas F. (codecasa)


Lesenswert?

Jetzt hab ich das Problem das wenn die char strA[20] drausen deklariert 
wird das er an jedem Menüpungt das Selbe komische Zeichen anzeigt :(




char *strTemp;
  char strA[20];

  int an = 0;
  for (int iP=0; iP<anzCMD; iP++)
  {



                   if (CMD[iP].Befehl == CMD_ZEIT)
                   {

                      strcpy(strA, "zeit");
                      strcat(strA, "(50);");
                      strcpy(strTemp ,strA);

                      an++;
                   }

von Krapao (Gast)


Lesenswert?

> wird das er an jedem Menüpungt das Selbe komische Zeichen anzeigt :(

Vollkommen logisch. Du kopierst hier

> strcpy(strTemp ,strA);

in die Pampa, weil

> char *strTemp;

nicht auf einen Speicherbereich initialisiert ist, der den String strA 
aufnehmen könnte. Das zermümpelt dir ein paar Variablen, die hinter 
strTemp im Speicher liegen. Mit allen unschönen Effekten.

von Andreas F. (codecasa)


Lesenswert?

Hallelulia ich habs endlich gerafft was Ihr mir seit 4 Tagen 
eintrichtern wollt :)


Wie einfach und ich mach mir 4 Tage ein Kopf :)


Ich habe einfach eine Mehrdimensionale Char Array deklariert sprich 
nicht nur Zeiger. char strA[15][15];

Und dann:

 int an = 0;
  for (int iP=0; iP<anzCMD; iP++)
  {
                   char pp1[10];
                   itoa(CMD[iP].param1,pp1,10);

                   char pp2[10];
                   itoa(CMD[iP].param2,pp2,10);


                   Serial.println(pp1);

                   if (CMD[iP].Befehl == CMD_ZEIT)
                   {
                      strcpy(strA[iP], "zeit(");
                      strcat(strA[iP], pp1);
                      strcat(strA[iP], ");");
                      mnuAddCMD(strA[iP]);
                   }
                   else if (CMD[iP].Befehl == CMD_PMP)
                   {
                      if(pp1 == "1") strcpy(pp1,"an"); else if(pp1=="0") 
strcpy(pp1,"aus");

                      strcpy(strA[iP], "pmp(");
                      strcat(strA[iP], pp1);
                      strcat(strA[iP], ");");
                      mnuAddCMD(strA[iP]);
                   }
                   else if (CMD[iP].Befehl == CMD_SAN)
                   {
                      if(pp1 == "1") strcpy(pp1,"an"); else if(pp1=="0") 
strcpy(pp1,"aus");

                      strcpy(strA[iP], "san(");
                      strcat(strA[iP], pp1);
                      strcat(strA[iP], ");");
                      mnuAddCMD(strA[iP]);
                   }
                   else if (CMD[iP].Befehl == CMD_START_IMP)
                   {

                      strcpy(strA[iP], "start_imp(");
                      strcat(strA[iP], pp1);
                      strcat(strA[iP], ",");
                      strcat(strA[iP], pp2);
                      strcat(strA[iP], ");");
                      mnuAddCMD(strA[iP]);
                   }
                   else if (CMD[iP].Befehl == CMD_STOP_IMP)
                   {

                      strcpy(strA[iP], "stop_imp()");
                      mnuAddCMD(strA[iP]);
                   }
                   else if (CMD[iP].Befehl == CMD_END)
                   {

                      strcpy(strA[iP], "end;");
                      mnuAddCMD(strA[iP]);
                   }

Und es läuft hehe

von DirkB (Gast)


Lesenswert?

Andreas Frauenstein schrieb:
> if(pp1 == "1")

Du hast es immer noch nicht verstanden. :-(

Da werden Zeiger verglichen und keine Inhalte.

pp1 ist die Adresse von deinem Array. "1" ist ein Stringliteral, das 
auch irgendwo im Speicher steht, also auch eine Adresse besitzt.

Du vergleichst also, ob dein Array an der gleichen Stelle liegt wie das 
Literal.

Das sind niedrigste C-Grundlagen.
Besorg dir unbedingt ein C-Buch und arbeite es durch.

von Master (Gast)


Lesenswert?

Andreas Frauenstein schrieb:
> *((char*)&CMD[iP] + t) = EEPROM.read(adrIP + (iP * sizeof(cmdP))

Eine read Funktion liefert normalerweise nur einen Pointer, d.h. der 
Compiler kann die Daten nicht automatisch an das Struct übergeben. Über 
ein memcpy() wäre es aber möglich.

Wer mit Strings arbeitet sollte sich die strcpy, strcmp usw. Funktionen 
anschauen. Es gibt den wenig schmeichelhaften Spruch, "String 
manipulation is pain in the ass", der aber einen Funken Wahrheit 
enthält.

von Karl H. (kbuchegg)


Lesenswert?

Andreas Frauenstein schrieb:
> Hallelulia ich habs endlich gerafft was Ihr mir seit 4 Tagen
> eintrichtern wollt :)
>
>
> Wie einfach und ich mach mir 4 Tage ein Kopf :)
>
>
> Ich habe einfach eine Mehrdimensionale Char Array deklariert sprich
> nicht nur Zeiger. char strA[15][15];
>

Und an dieser Stelle erhebt sich dann die Frage, ob es taktisch gesehen 
nicht einfacher wäre, das String-Array gleich in den Menüpunkt selber zu 
verfrachten
1
class Menu
2
{
3
private:
4
 Menu * parent;//Parent Menu, NULL if this is the top
5
 Menu * child;//First Child Menu, NULL if no children
6
 Menu * sibling;//Next Sibling Menu, NULL if this is the last sibling
7
8
 void setParent(Menu &p);//Sets the Menu's Parent to p
9
 void addSibling(Menu &s,Menu &p);//Adds a Sibling s with Parent p.  If the Menu already has a sibling, ask that sibling to add it
10
public:
11
 char name[15];  //  <-------
12
....

Dann hat jedes Menüpunkt seine eigene Speicherfläche und ist in sich 
konsistent und hängt von nichts ausserhalb ab.

(Und gleich noch ein PS hinten nach:
Als Verwender, was interessiert dich von einer Klasse am meisten? Dich 
interessiert, welche Methoden sind public! Was hingegen interessiert 
dich (als Verwender) überhaupt nicht? Dich interessiert überhaupt nicht, 
welche Methoden oder Member private sind. Warum interessiert dich das 
nicht? Weil du eh nichts damit tun kannst. Genau deshalb sind sie ja 
private, damit du als Verwender nichts damit tun kannst!
Warum kommen daher in deiner Klassenbeschreibung die private Member 
zuerst? Die interessieren aus der sicht desjenigen, der die Klasse 
einsetzt, keine Sau! Alles was du tust ist, du nötigst mich dazu, dass, 
wenn ich nachsehen will, was die Klasse eigentlich kann, ich erst mal 
Minutenlang durch Code durch-waten muss, ehe ich dann endlih die Member 
gefunden habe, die mich interessieren - die public sind.

von Krapao (Gast)


Lesenswert?

@ Master

>> EEPROM.read
> Eine read Funktion liefert normalerweise nur einen Pointer

Die EEPROM.read aus der Arduino-Library nicht. Die liefert ein Byte.
http://arduino.cc/it/Reference/EEPROMRead

@ Karl Heinz Buchegger

> Und an dieser Stelle erhebt sich dann die Frage, ob es taktisch gesehen
> nicht einfacher wäre, das String-Array gleich in den Menüpunkt selber zu
> verfrachten

Einfacher ja. Vergrößert aber den RAM Bedarf und wenn diese Ressource 
auf dem µC knapp ist, schiesst man sich mit der einfachen Taktik selbst 
ins Knie.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Krapao schrieb:
> Einfacher ja. Vergrößert aber den RAM Bedarf und wenn diese Ressource
> auf dem µC knapp ist, schiesst man sich mit der einfachen Taktik selbst
> ins Knie.

Ich vermute mal das diese Menüklasse (irgendwo gab es die die letzten 
Tage doch schon mal...) auch gar nicht so richtig für das dynamische 
anlegen neuer Menüpunkte konzipiert ist, sonder eher davon ausgeht, dass 
das Menü einmal Initial befüllt wird und dann sozusagen 
"compile-time-constant" ist (was dem Compiler wohl dann auch ermöglicht 
das ganze etwas effizienter zu machen).

von Karl H. (kbuchegg)


Lesenswert?

Krapao schrieb:

> Einfacher ja. Vergrößert aber den RAM Bedarf und wenn diese Ressource
> auf dem µC knapp ist, schiesst man sich mit der einfachen Taktik selbst
> ins Knie.

Muss man sich im Detail ansehen.
Ich gebe zu bedenken, dass da ansonsten ein Pointer in der Klasse 
rumlungert, der auch wieder Speicher braucht. Es hängt vieles davon ab, 
wieviele Menüpunkt konstante Texte sind und wieviele tatsächlich 
dynmisch Texte erhalten.

von Andreas F. (codecasa)


Angehängte Dateien:

Lesenswert?

Aslo ich habe jetzt im Anhang nochmal den Aktuellen Code

Habe wieder zwei Tage grätselt warum die load_Programm jetzt serial_up - 
Fuktion nur mist macht es war wieder der RAM weil ich zuviele unnütze 
Char[] oder char * Variablen  habe !

Ich habe jetzt ab Menüpunkt 3 sprich Geräteinfo alle Menüs entfernt und 
siehe da das hat schon ausgereicht damit ich weiter arbeiten kann aber 
zufrieden bin ich lange noch nich da ich Die Programme die Seriell 
hochgeladen wurden bei betätigen einer Starttaste mit Millis 
implementieren muss.


Es wäre doch bestimmt ratsamm die Bufferung im CMD direkt wegzulassen 
und bei einem Seriellen Upload direkt im EEprom zu speichern und bei 
Enter Auf Job01 Die Menus dierekt mit dem Daten aus dem EEProm zu 
erstellen und bei verlassen des Menüs 11 Direkt den Speicher von den 
Erstllten Menüs wieder freizugeben oder ?

Ich will den Controller jetzt ersteinmal zum ersten Vorführen benutzen 
bei fortschritt des Projekts sollte ich wahrscheinlich einen anderen 
Controller mit mehr RAM einbauen was könnt Ihr empfehlen.

geplan sind noch:
Verschiedene z.B max 10 Programme (*.ic Dateine = TXT format) von SD 
Karte nach abruf der Menüpunkte:
job01
job02
job03
job04
job05
job06
job07
job08
job09
job10

Und eventuel noch ein Parr Sensoren Druck und ein Wasser-Magnet-Ventil

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.