*Markus: Kuriosität mit Inkrementierung

Hallo,

ich bin auf ein seltsames Problem gestoßen, das ich mir nicht erklären kann. Ich habe folgende Schleife bei der "Konten" mithilfe des übergebenen Index aus einer "KontoVerwaltung" gelöscht werden können:

  
     public boolean loeschen(int index)    {  
          if (index >= 0 && index < anzahl)    {  
             int i = index;  
             while (i < anzahl)    {  
                 konten[i++] = konten[i+1];  
             }  
             konten[i] = null;  
             anzahl--;  
             return true;  
          }  
          return false;  
     }  

Der Teil in der while-Schleife liefert eine NullPointerException aufgrund der Inkrementierung innerhalb der eckigen Klammern. Inkrementiere ich i außerhalb der Klammer, funktioniert es.
Kann sich das jemand erklären?
Komischerweise würde auch ++i funktionieren, woraufhin die Funktion aber ein verständlicherweise falsches Ergebnis liefert.

Markus.

--
http://www.apostrophitis.at
Maschiene währe Standart Gallerie vorraus Packete Objeckte tollerant vieleicht Strucktur
  1. Hi,

    konten[i++] = konten[i+1];
    Der Teil in der while-Schleife liefert eine NullPointerException aufgrund der Inkrementierung innerhalb der eckigen Klammern. Inkrementiere ich i außerhalb der Klammer, funktioniert es.
    Kann sich das jemand erklären?

    Gegenfrage: Was glaubst Du denn sei der Rückgabewert(!) von i++?

    Komischerweise würde auch ++i funktionieren,

    Und was gibt im Gegensatz dazu ++i zurück?

    Cheatah

    --
    X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
    X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
    X-Will-Answer-Email: No
    X-Please-Search-Archive-First: Absolutely Yes
    1. Hallo,

      Gegenfrage: Was glaubst Du denn sei der Rückgabewert(!) von i++?

      Wie meinst du das mit dem Rückgabewert? Meiner Logik zufolge müsste doch
      konten[i++] = konten[i+1] bewirken, dass zuerst die nächst höhere Referenz konten[i] zugewiesen wird, und dann i inkrementiert wird. Ich bilde mir ein, in Perl würde das so funktionieren.

      Und was gibt im Gegensatz dazu ++i zurück?

      ++i bewirkt, dass genau jenes Konto gelöscht wird, das sich eine Position "oberhalb" des übergebenen Index befindet.

      Markus.

      --
      http://www.apostrophitis.at
      Maschiene währe Standart Gallerie vorraus Packete Objeckte tollerant vieleicht Strucktur
      1. gudn tach!

        [...] müsste doch
        konten[i++] = konten[i+1] bewirken, dass zuerst die nächst höhere Referenz konten[i] zugewiesen wird, und dann i inkrementiert wird. Ich bilde mir ein, in Perl würde das so funktionieren.

        ja, und den anderen sprachen mit c-syntax ebenfalls.

        prost
        seth

        1. Hallo,

          ja, und den anderen sprachen mit c-syntax ebenfalls.

          Das heißt also, dass es eine Java-Eigenheit ist, und kein logischer Fehler?

          Markus.

          --
          http://www.apostrophitis.at
          Maschiene währe Standart Gallerie vorraus Packete Objeckte tollerant vieleicht Strucktur
          1. gudn tach!

            ja, und den anderen sprachen mit c-syntax ebenfalls.

            Das heißt also, dass es eine Java-Eigenheit ist, und kein logischer Fehler?

            nein, java zaehle ich zu den sprachen mit c-syntax.

            dein fehler liegt, wie in diesem posting bereits angedeutet, wahrscheinlich an dem zugriff auf konten[anzahl].

            ich wuerde es so

              
            while (i<anzahl-1)  
              konten[i++] = konten[i+1];
            

            oder so

              
            for(int i=index; i<anzahl-1; ++i)  
              konten[i] = konten[i+1];  
            konten[--anzahl] = null;
            

            schreiben.

            wobei das noch ausser acht laesst, dass es fuer sowas bessere datenstrukturen gibt (hat Richard ja in https://forum.selfhtml.org/?t=129973&m=840415 auch schon angesprochen).

            prost
            seth

            1. Hallo,

              dein fehler liegt, wie in diesem posting bereits angedeutet, wahrscheinlich an dem zugriff auf konten[anzahl].

              Also nach langem Herumtesten und Fehler ausmerzen kam ich zwar drauf, dass es while (j+1 < anzahl) heißen muss, damit bei einer vollen Kontoverwaltung kein OutOfBoundsException entsteht, aber nichts desto trotz funktioniert i++ innerhalb der eckigen Klammern nicht.
              Es ist mir unbegreiflich, da i++ außerhalb und innerhalb eigentlich in der Gesamtheit der Schleife identisch sind.

              Markus.

              --
              http://www.apostrophitis.at
              Maschiene währe Standart Gallerie vorraus Packete Objeckte tollerant vieleicht Strucktur
              1. gudn tach!

                nichts desto trotz funktioniert i++ innerhalb der eckigen Klammern nicht.

                oops, du hattest eben mit der vermutung recht. java macht es doch anders als c++.

                habe auch einen langer thread ueber das thema in einem anderen forum gefunden (aber nicht alles gelesen).

                nun java macht es also anders.

                code:
                  konten[i++] = konten[i+1];

                ist in c++:
                  konten[i] = konten[i+1]; ++i;

                und in java:
                  konten[i] = konten[++i+1];

                c++ wartet auf das ende der gesamten anweisung vor dem inkrementieren und java inkrementiert sofort nach dem teilausdruck.

                wenn du also
                  konten[i] = konten[i++ +1];
                schreiben wuerdest, funzt auch in java.

                prost
                seth

                1. Hallo,

                  c++ wartet auf das ende der gesamten anweisung vor dem inkrementieren und java inkrementiert sofort nach dem teilausdruck.

                  Alles klar, das würde das Verhalten meiner Methode erklären. :)

                  wenn du also
                    konten[i] = konten[i++ +1];
                  schreiben wuerdest, funzt auch in java.

                  Das sind natürlich Konstrukte, die man eher meiden sollte, wovon mich mein Lehrer auch schon immer warnte :)

                  Markus.

                  --
                  http://www.apostrophitis.at
                  Maschiene währe Standart Gallerie vorraus Packete Objeckte tollerant vieleicht Strucktur
      2. Hi,

        Gegenfrage: Was glaubst Du denn sei der Rückgabewert(!) von i++?
        Wie meinst du das mit dem Rückgabewert?

        damit meine ich, dass jede Operation - egal ob Aufruf einer Methode, Abgreifen eines Variablenwertes, Durchführen einer Inkrementierung oder was auch immer - in ihren Kontext eine Rückgabe liefert. Wie lautet die Rückgabe der Operation "i++"?

        Meiner Logik zufolge müsste doch konten[i++] = konten[i+1] bewirken,

        Was es bewirkt ist egal. Was liefert i++ zurück? Was liefert i+1 zurück? Was liefert ++i zurück?

        [...] und dann i inkrementiert wird.

        Der Einfluss auf i hat mit dieser meiner Frage übrigens nichts zu tun.

        Cheatah

        --
        X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
        X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
        X-Will-Answer-Email: No
        X-Please-Search-Archive-First: Absolutely Yes
        1. Hallo,

          Was es bewirkt ist egal. Was liefert i++ zurück? Was liefert i+1 zurück? Was liefert ++i zurück?

          Es liefert WAHR zurück. Es wäre mir angenehm, wenn du mich nicht herumraten lassen würdest, sondern mir konkret sagen könntest, warum das so nicht funktioniert.
          Ich habe die kompletten Beispiele mal hier hochgeladen:
          http://test.pithax.net/Konto.java
          http://test.pithax.net/KontoVerwaltung.java

          Markus.

          --
          http://www.apostrophitis.at
          Maschiene währe Standart Gallerie vorraus Packete Objeckte tollerant vieleicht Strucktur
          1. Hi,

            Was liefert i++ zurück? Was liefert i+1 zurück? Was liefert ++i zurück?
            Es liefert WAHR zurück.

            auf welche meiner drei Fragen ist das die Antwort? Und was genau steht in konten[WAHR]?

            Es wäre mir angenehm, wenn du mich nicht herumraten lassen würdest, sondern mir konkret sagen könntest, warum das so nicht funktioniert.

            Nein, ich lasse Dich lieber nachdenken, wie man einem Problem auf die Spur kommt. Davon haben wir beide und eventuelle Mit- und Nachleser nämlich sehr viel mehr.

            Cheatah

            --
            X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
            X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
            X-Will-Answer-Email: No
            X-Please-Search-Archive-First: Absolutely Yes
            1. gudn tach!

              ich lasse Dich lieber nachdenken, wie man einem Problem auf die Spur kommt. Davon haben wir beide und eventuelle Mit- und Nachleser nämlich sehr viel mehr.

              ich fand aber innerhalb dieses threads deine beitraege nicht hilfreich[1]. und selbst jetzt, wo ich die java-funktionsweise diesbzgl. kenne, weiss ich immer noch nicht, ob du wirklich auf dasselbe hinauswolltest.

              prost
              seth

              [1] ich bewerte sie jedoch nicht als "nicht hilfreich", weil ich eher vermute, dass ich mich einfach bloss beim verstehen zu doof anstelle.

            2. Hallo,

              Nein, ich lasse Dich lieber nachdenken, wie man einem Problem auf die Spur kommt. Davon haben wir beide und eventuelle Mit- und Nachleser nämlich sehr viel mehr.

              Das finde ich absolut nicht. Warum glaubst du zu wissen, was für mich oder andere am besten ist? Dieses Herumraten meinerseits erscheint mir für viele nicht sehr hilfreich zu sein, da sich sämtliche Mitleser erst durch dutzende Postings, durch mein Raten verursacht, wühlen müssen, um folgen zu können. Manche lernen nur dann gut, wenn sie im Zimmer auf- und abgehen. Andere können nur hinterm Schreibtisch lernen.
              Ich wiederum, wie wahrscheinlich viele andere Leute, lerne am besten anhand von vielen Beispielen. Du denkst vielleicht, dass man auf diese Weise schnell dazu verleitet wird, sich die Lösung zu jedem noch so kleinen Problem von den anderen vorkauen lässt und denkfaul wird, was sicher oft zutrifft.
              Ich kann mich aber nicht erinnern, je eine Frage hier gestellt zu haben, die ich mir ein paar Minuten später vielleicht hätte selbst beantworten können.

              Markus.

              --
              http://www.apostrophitis.at
              Maschiene währe Standart Gallerie vorraus Packete Objeckte tollerant vieleicht Strucktur
  2. Hallo,

    Ich glaube, du wendest den Inkrementationsoperator ganz einfach falsch an. i wird innerhalb der eckigen Klammern, und nirgendwo anders, hochgezählt. Beim nächsten while-Durchlauf ist es wieder i und nicht i+1.

    Viele Grüße

    --
    Wer ist eigentlich LAN und warum macht er so viele Partys?
    Das beste Freeware-Programm der Welt
    Selfcode: ie:( fl:| br:^ va:| ls:[ fo:) rl:( n4:| ss:| de:[ js:| ch:? sh:( mo:) zu:|
    1. Hallo,

      Ich glaube, du wendest den Inkrementationsoperator ganz einfach falsch an. i wird innerhalb der eckigen Klammern, und nirgendwo anders, hochgezählt. Beim nächsten while-Durchlauf ist es wieder i und nicht i+1.

      i wurde außerhalb der Schleife definiert wodurch es seinen Wert innerhalb der Schleife nicht einfach so wieder verlieren kann.

      Markus.

      --
      http://www.apostrophitis.at
      Maschiene währe Standart Gallerie vorraus Packete Objeckte tollerant vieleicht Strucktur
      1. Hallo,

        i wurde außerhalb der Schleife definiert wodurch es seinen Wert innerhalb der Schleife nicht einfach so wieder verlieren kann.

        Um die Schleife aber überhaupt schleifen zu lassen, muss i selbst inkrementiert werden:

          
        while(i < anzahl) {  
          kosten[i] = 100;  
          i++;  
        }  
        
        

        Viele Grüße

        --
        Wer ist eigentlich LAN und warum macht er so viele Partys?
        Das beste Freeware-Programm der Welt
        Selfcode: ie:( fl:| br:^ va:| ls:[ fo:) rl:( n4:| ss:| de:[ js:| ch:? sh:( mo:) zu:|
        1. Hello out there!

          Um die Schleife aber überhaupt schleifen zu lassen, muss i selbst inkrementiert werden

          Wird es doch.

          Der Unterschied von

            while(i < anzahl) {  
              kosten[i] = 100;  
              i++;  
            }
          

          zu

            while(i < anzahl) {  
              kosten[i++] = 100;  
            }
          

          bzw.

            while(i < anzahl) {  
              kosten[++i] = 100;  
            }
          

          wäre welcher?

          See ya up the road,
          Gunnar

          --
          “Remember, in the end, nobody wins unless everybody wins.” (Bruce Springsteen)
          1. Hallo,

            OK, jetzt hab ich nochmal nachgelesen.

            BTW:
            @*Markus: Für dynamische Datenstrukturen bieten sich doch anstelle von simplen Arrays eher ArrayLists oder HashMaps an, oder nicht? Durch die kann man bequem durch-iterieren und an gewünschter Stelle removen.

            Viele Grüße

          2. gudn tach!

            Der Unterschied von

            while(i < anzahl) {

            kosten[i] = 100;
                i++;
              }

            
            >   
            > zu  
            >   
            > ~~~java
            
              while(i < anzahl) {  
            
            >     kosten[i++] = 100;  
            >   }
            
            

            bzw.

            while(i < anzahl) {

            kosten[++i] = 100;
              }

            
            >   
            > wäre welcher?  
              
            hmmpf, ich hatte hierauf eben schon mal geantwortet, aber mal wieder vergessen, nach der vorschau noch mal auf absenden zu klicken.  
              
            naja, war eh nur ein verlinkter hinweis auf die loesung.  
            und da Richard jetzt eh bescheid weiss, sag ich's halt dem archiv:  
            beispiel 1 und 2 sind aequivalent, beispiel 3 macht was anderes. das erklaeren einem sehr viele seiten im internet, sogar auf deutsch; stichwort: "inkrementierungsoperator".  
              
            prost  
            seth
            
  3. gudn tach!

    while (i < anzahl)    {
                          ^^^^^^^^
                     konten[i++] = konten[i+1];
                                          ^^^

    wobei ich hier nur rate, was anzahl ist.

    prost
    seth

  4. Hallo *Markus,

    Der Teil in der while-Schleife liefert eine NullPointerException aufgrund der Inkrementierung innerhalb der eckigen Klammern.

    Das dürfte eine ArrayIndexOutOfBounds-Exception sein. Eine NullPointerException könnte höchstens dann auftreten, wenn konten = null wäre.

    Der nächste Punkt:
    konten[i++] = konten[i+1];
    Hier hab' ich erst mal überlegt, ob eigentlich zuerst die rechte Seite der Zuweisung oder i++ ausgewertet wird. Ziehe das i++ da lieber raus oder in den Kopf einer for-Schleife. Solche Trickserreien verwirren nur und bringen nichts.

    Was bereits schon angedeutet wurde: Warum versuchst Du Dir selber so eine Krücke zu basteln, wenn Java fertige, ausgereifte Datenstrukturen mitbringt? Geeignet wäre z.B. ArrayList. Der einzige Grund, in so einem Fall direkt mit Arrays rumzubasteln, wäre, dass es sich um eine Übungsaufgabe handelt oder dass man aus Performancegründen o.ä. eine sehr genaue Kontrolle darüber will, wann neue Arrays angelegt und Daten zwischen Arrays kopiert werden.

    Grüße

    Daniel

    1. Hallo,

      Was bereits schon angedeutet wurde: Warum versuchst Du Dir selber so eine Krücke zu basteln, wenn Java fertige, ausgereifte Datenstrukturen mitbringt?

      Ich weiß schon, auch dank der Hinweise hier, dass es einfach ginge, aber mir ging es hauptsächlich nur um das Verständnis dahinter, da ich gerne ausprobiere was in den verschiedenen Sprachen so alles funktionert.

      Markus.

      --
      http://www.apostrophitis.at
      Maschiene währe Standart Gallerie vorraus Packete Objeckte tollerant vieleicht Strucktur
  5. gudn tach!

    while (i < anzahl)    {

    hier war ja schon der erste fehler.

    konten[i++] = konten[i+1];

    und hier ist in java der zweite. in c++ waer's richtig.

    warum ich jetzt trotz der anderen postings mich noch mal melde:
    ich hab's jetzt auch im manual gefunden:

    15.7.2 Evaluate Operands before Operation

    in java also
      konten[i++] = konten[i];
    oder
      konten[i] = konten[i++ +1];
    oder gleich
      konten[i] = konten[++i];

    prost
    seth

    1. Hallo seth,

      Eigentlich ist 15.7.1  Evaluate Left-Hand Operand First relevant oder wem das noch zu unspezifisch ist 15.26.1 Simple Assignment Operator =.
      In diesem Abschnitt steht explizit, dass der Unterausdruck einer Arrayreferenz zuerst ausgewertet wird.

      Deine Folgerungen daraus sind allerdings richtig. Die Tatsache, dass man, um den Code zu verstehen und zu korrigieren erst einmal die Sprachspezifikation im Detail lesen muss, bestätigt mich allerdings darin, dass man das so nicht machen sollte.

      Grüße

      Daniel