Magisches Quadrat Endlosschleife



  • Guten Abend,

    Ich habe mal wieder ein kleines Problem.
    Und zwar sollte ich ein Programm programmieren das ein magisches Quadrat ausgibt.. die anzahl der felder soll variable sein.

    Nur leider habe ich bei meinem Programm eine Endlosschleife bei der Eingabe eingebaut und kriege sie nicht weg. Ob das Programm dann funktioniert weiß ich nicht da ich es ja noch nicht ausprobioeren konnte.

    Zur erklärung: ein magisches Quadrat ist ein Quadrat wo jede Zeile und spalte das selbe ergebnis hat. Zudem darf keine zahl doppelt vorkommen.

    z.B.

    8.1.6 = 15
    3.5.7 = 15
    4.9.2 = 15
    | .| .|
    15.15.15
    ich hoffe ihr könnt mir helfen.

    //----------------------------------------------------------
    #include <iostream>
    #include <iomanip>
    #include <cstdio>
    using namespace std;
    //----------------------------------------------------------
    int main ()
    {
    int z, s, N, max=21, wert=1;
    int mq[max][max];
    do
    {
        cout <<"Bitte geben Sie die Groesse der Tabelle ein (Ungrade Zahlen): " <<endl;
        cin >> N;
    }
    while (N % 2);
    for (z=0; z<N; z++)
    {
        for (s=0; s<N; s++)
        {
            mq[z][s] = 0;
        }
    }
    z=(N+3)/2-1;
    s=(N+1)/2-1;
    mq[z][s] =wert;
    wert++;
    do
    {
           s++;
           z++;
           if (z>N-1)
           {
                     z=0;
           }
           if (s>N-1)
           {
                     s=0;
           }
           if (mq[z][s] != 0)
           {
                        s--;
                        z++;
                        if (s<0)
                        {
                                s=N-1;
                        }
                        if (z>N-1)
                        {
                                  z=0;
                        }
                        if (mq[z][s] !=0)
                        {
                        }
                        else
                        {
                        mq[z][s] =wert;
                        wert++;
                        }            
           }
           else
           {
               mq[z][s] =wert;
               wert++;
           }
    }
           while (wert <=N*N);
           for (z=0;z<N;z++)
           {
               for (s=0; s<N; s++)
               {
                   cout << mq[z][s];
               }
               cout <<endl;
           }
           system ("pause");
    }
    


  • Die Endlos Schleife passiert nicht bei der Eingabe, sondern nachher.

    Schau mal diese Bedingung an:

    while (wert <=N*N);
    

    und dann was du hier machst:

    if (z>N-1)
           {
                     z=0;
           }
    

    Kann wert überhaupt einmal die Schleifen Bedingung nicht erfüllen?

    Wenn du deinen Code ein wenig besser ordnen würdest, dann würdest du so etwas schneller sehen. Oder du benutzt einen Debugger, damit findest du solche Fehler meistens sehr schnell (ich habe ein paar Sekunden gebraucht diesen Fehler zu finden ohne deinen Code wirklich anschauen zu müssen).

    //EDIT:
    Das ist dann kein korrekter C++ Code. Alleine das max müsste eine Konstante sein, damit es überhaupt kompiliert.



  • Die do-while-Schleife wird beendet, wenn die Bedingung false ist. Und wenn du mit Zahlen arbeitest, gilt 0 als falsch - d.h. deine Eingabeschleife wird erst beendet, wenn N%2==0 ist (d.h. bei einer geraden Zahl).
    (das ist ein Grund dafür, solche Konstruktionen zu vermeiden, wenn man nicht genau weiß was man macht :D)

    Ansonsten hast du noch ein Problem, wenn du einen Buchstaben eingibst - dann hast du eine echte Endlosschleife, weil cin die Arbeit verweigert. Und wenn du größere magische Quadrate als 21x21 berechnen willst, kracht es im späteren Verlauf.

    PS: Deinen Algorithmus habe ich mir jetzt nicht näher angesehen.

    Edit @drakon: Was du da bemängelt hast, ist übrigens nur das Ende einer längeren do-while-Schleife, die allerdings ein wenig unglücklich formatiert ist 😉



  • @CStoll
    Dass man nur ungerade Zahlen eingeben kann ist Absicht. Das geht ja schon von der Konsolen Ausgabe vorher aus. (viel Sinn macht die Schleife dort denke ich aber sowieso nicht.. der Wert wird ja ständig überschrieben..)



  • z=(N+3)/2-1;
    s=(N+1)/2-1;
    mq[z][s] =wert;
    

    Wer garantiert dir, dass N nicht so groß ist, dass du eine Schutzverletzung produzierst?

    Wenn du dir unsicher bist, wo genau der Fehler liegt, warum baust du dann nicht Debug ausgaben ein.
    Dann kannst du anhand deines Codes schnell nachvollziehen welcher Block die Endlosschleife bildet und evtl gibst du ja auch mal den Wert aus, durch dessen Veränderung die Schleife beendet werden könnte.

    Dann weisst du wo, und warum du eine Endlosschleife hast, und kannst dir Gedanken machen, wie du diese los wirst.



  • drakon schrieb:

    @CStoll
    Dass man nur ungerade Zahlen eingeben kann ist Absicht. Das geht ja schon von der Konsolen Ausgabe vorher aus.

    Genau da liegt das Problem - bei einer ungeraden Zahl wird die Schleifenbedingung wahr und du landest wieder am Anfang der Schleife.



  • Dass ist mir klar, aber das ist auch die Ursache der Endlos Schleife (die der TO meint.. falsche Eingabe wird er ja selbst nicht machen..).

    Ich habe die von mir genannte Bedingung dann mal rausgenommen und dann ist sein Programm zu Ende gelaufen. - Die Zeit das im Kopf durchzugehen nehme ich mir hier nicht. 😉

    @CStoll:
    Wir schreiben viel zu schnell.. ^^
    Ich weiss nicht genau was er damit erreichen will, aber ich denke mal, dass er nicht diese Endlosschleife meinte, weil er da ja die Ausgabe sieht und im Text schreibt er ja Mehrzahl "ungerade Zahlen". Also erwartet er da irgendwie auch mehrere Zahlen. Sinn macht das denke ich überhaupt keinen, aber nachher hat man wirklich eine Endlosschleife, ohne die Möglichkeit sie durch Input abzubrechen.



  • *schaut sich doch nochmal den Algorithmus an*

    Die Hauptarbeit wird in einer großen do{...}while(wert<=N*N); Schleife verrichtet. In dieser Schleif wird wert auch gelegentlich erhöht, könnte also irgendwann das Ende erreichen. Ich hab' allerdings den Überblick verloren, ob die Schleife wirklich alle Felder des N*N Sub-Arrays erreicht und sich nicht auf einem Teil des Arrays im Kreis drehen wird auf der Suche nach dem nächsten freien Feld.

    Die Eingabe (Maik erwähnte eine "Endlosschleife bei der Eingabe") hat wie gesagt das Abbruchkriterium umgedreht - bei Eingabe einer ungeraden Zahl fragt sie nochmal, bei einer geraden Zahl geht sie weiter in die Initialisierungsschleife, wenn etwas nicht interpretierbares kommt (z.B. ein x), füllt sie den Bildschirm mit "Bitte geben Sie...".

    drakon schrieb:

    @CStoll:
    Wir schreiben viel zu schnell.. ^^

    Kann schon sein 😃



  • Ich habe mich da denke ich ein wenig verguckt.

    Aber sagen wir, dass er nicht das Input Problem meinte. Wenn man eine gerade Zahl eingibt, dann kommt man aus der Schleife raus. Ist also eigentlich keine Endlosschleife, weil sie durchaus terminiert (bei günstiger Eingabe).

    Die Ausschnitte, die ich gezeigt habe haben direkt nichts zu tun. Ich hatte mich da irgendwie verguckt und z und wert verwechselt.
    Auf jeden Fall gibt es eine Endlosschleife in der zweiten loop. Und wenn man die von mir gezeigte Bedingung weglässt, dann terminiert das ganze und es wird etwas ausgegeben. Warum das so ist lasse ich jetzt mal dem TO rauszufinden. ^^

    Dass die zweite Schleife terminiert nur weil in gewissen Pfaden "wert" verändert wird heisst nicht, dass die Schleife terminieren muss. Es muss in jeder Iteration ein Fortschritt gemacht werden, was hier denke ich nicht der Fall ist => Endlosschleife.

    Wie gesagt. Ich habe hier einfach den pragmatischen Ansatz genommen und den Code nicht verstehen wollen, sondern einfach mal ausgeführt und mit den erwarteten Werten gefüllt und die daraus resultierende Endlosschleife ist imo nicht die beim Input, sondern erst nachher. Dass der TO "beim input" geschrieben hat ordne ich jetzt wenig Gehalt zu, weil Fragende den Fehler oftmals am falschen Ort suchen. 😉



  • drakon schrieb:

    Dass die zweite Schleife terminiert nur weil in gewissen Pfaden "wert" verändert wird heisst nicht, dass die Schleife terminieren muss. Es muss in jeder Iteration ein Fortschritt gemacht werden, was hier denke ich nicht der Fall ist => Endlosschleife.

    Genau das meinte ich mit dem "im Kreis drehen" - in jedem Schleifendurchlauf wird x und y geändert, so daß er diagonal durch das Array läuft. Das kann gut gehen und tatsächlich alle Felder des Arrays erreichen, aber es kann genausogut in einer geschlossenen Schleife enden, bei der einige Felder nie erreicht werden. Um herauszufinden, was tatsächlih passiert, müsste jemand das Ganze schrittweise im Debugger beobachten.
    (ich hab' gerade keinen greifbar)

    Ansonsten erfahren wir weitere Details wohl nur, wenn wir Maik mal zu Wort kommen lassen.



  • Zeit das mit dem Debugger zu analysieren was er da genau (falsch) macht habe keine, aber ich habe es wie gesagt kurz getestet und die zweite Schleife hat nicht terminiert innerhalb von ein paar Sekunden, also wirt das mit einer grossen Wahrscheinlichkeit eine Endlosschleife sein.
    Ich habe aber ja auch noch was genannt, wie man diese durchbrechen kann und da sollte der TO ansetzen.

    Ich frage mich manchmal wie lange die Leute denken, dass sie hier für eine Antwort warten müssen, dass sie sich so lange nicht mehr blicken lassen.. ^^



  • CStoll schrieb:

    Die do-while-Schleife wird beendet, wenn die Bedingung false ist. Und wenn du mit Zahlen arbeitest, gilt 0 als falsch - d.h. deine Eingabeschleife wird erst beendet, wenn N%2==0 ist (d.h. bei einer geraden Zahl).
    (das ist ein Grund dafür, solche Konstruktionen zu vermeiden, wenn man nicht genau weiß was man macht :D)

    So mit ==0 habe ich wenigstens schonmal das Endlosding behoben (:. Nur wenn man jetzt 5 Eingibt kommt beispielsweise heraus:
    00703
    400080
    05009
    100100
    06020

    Irgendwo muss doch noch ein denkerfehler leigen aber so 😕



  • Die Lösung wurde schon ein paar mal genannt: Debugger. Außerdem solltest du dir genau überlegen, wie dein Algorithmus funktionieren soll - und das damit vergleichen, was er tatsächlich macht.
    (PS: und setz Leerzeichen zwischen die einzelnen Zahlen, das erleichtert dir die Unterscheidung zwischen "1 23" und "12 3" ;))



  • CStoll schrieb:

    Die Lösung wurde schon ein paar mal genannt: Debugger. Außerdem solltest du dir genau überlegen, wie dein Algorithmus funktionieren soll - und das damit vergleichen, was er tatsächlich macht.
    (PS: und setz Leerzeichen zwischen die einzelnen Zahlen, das erleichtert dir die Unterscheidung zwischen "1 23" und "12 3" ;))

    Ich habe mich ja extra hier angemeldet um was zu lernen oder Probleme zu lösen 😉
    Ich bin noch kein Fachmann in C+ da ich vor gut einem viertel jahr angefangen habe c++ zu lernen.
    Daher tut es mir leid das ich nicht weiß was ein Debugger macht oder was ich für ein Programm brauche!
    um das Schreiben "benutz Google" vorweg zunehmen werde ich mich da morgen mal schlau machen.
    Gute nacht an alle
    mfg

    Um noch etwas dran zu hängen..
    Herausgefunden habe ich auch das mein Programm bei einer Eingabe von 5 genau die zahlen von 1 bis 10 ausgibt also 5*2 bei einer Eingabe von 11 wären das denn die Zahlen 1-22 // 11*2 Den rest füllt er einfach mit Nullen was er nciht darf 😃



  • In Kurzfassung: Mit dem Debugger kannst du Schritt für Schritt beobachten, wie dein Code abgearbeitet wird (inklusive der Variablenwerte). Die genauen Möglichkeiten unterscheiden sich dabei, aber die meisten Entwicklungsumgebungen dürften einen dabei haben.
    (womit entwickelst du eigentlich?)



  • CStoll schrieb:

    (womit entwickelst du eigentlich?)

    Ich hatte einmal wScite nur da funktioniert der compiler nicht und mit dem Programm womit ich alle mache heißt Dev c++ andere kenn ich nicht 😕
    Für neue Vorschläge immer offen



  • MaiKzZ schrieb:

    mit dem Programm womit ich alle mache heißt Dev c++ andere kenn ich nicht 😕

    Ich denke mal, wenn du damit zufrieden bist, kannst du auch dabei bleiben (aber ich kenne mich nicht gut genug mit den Entwicklungsumgebungen aus, um da eine Empfehlung auszusprechen). Und eine kurze Google-Recherche verrät auch, daß er einen Debugger mitliefert.



  • hol dir visual C++ 2010 express edition
    der ist besser, schneller, schöner, cooler, sicherer, effektiver, stabiler, cooler, hilfreicher, hab ich cooler schon erwähnt?

    und kostenlos und aktuell !
    und das debuggen ist auch nicht mehr als ein mausklick (oder doppelklick)



  • Skym0sh0 schrieb:

    hol dir visual C++ 2010 express edition

    habe ich mir gleich mal geladen und getest.
    soweit funktioniert alles
    jedoch nach dem Debuggen sagt er :

    "Magisches Quadrat.exe": "C:\Users\maik\Desktop\Magisches Quadrat\Debug\Magisches Quadrat.exe" geladen, Symbole wurden geladen.
    "Magisches Quadrat.exe": "C:\Windows\System32\ntdll.dll" geladen, Cannot find or open the PDB file
    "Magisches Quadrat.exe": "C:\Windows\System32\kernel32.dll" geladen, Cannot find or open the PDB file
    "Magisches Quadrat.exe": "C:\Windows\System32\KernelBase.dll" geladen, Cannot find or open the PDB file
    "Magisches Quadrat.exe": "C:\Windows\System32\msvcp100d.dll" geladen, Symbole wurden geladen.
    "Magisches Quadrat.exe": "C:\Windows\System32\msvcr100d.dll" geladen, Symbole wurden geladen.
    Der Thread 'Win32-Thread' (0x554) hat mit Code -1073741510 (0xc000013a) geendet.
    Das Programm "[5532] Magisches Quadrat.exe: Systemeigen" wurde mit Code -1073741510 (0xc000013a) beendet.

    Ist das normal oder hab ich irgendetwas falsch installiert ?

    P.S. Ich habe mit eurer Hilfe nun mein Programm fertig (: es fuinktioniert.
    Vielen Danke! Es war einfach nur die erste do-while Schliefe falsch.
    vielen vielen Danke.
    solltet ihr wissen wollen wie der fertige quellcode aussieht kann ich ihn gerne noch einmal posten.
    mfg



  • Den Debugger benutzt man normalerweise mit Breakpoints, die kann man setzen (wie kommt auf die IDE an). Das Programm startet und wird dann bis zum Breakpoint ausgeführt und angehalten, dann kannst du in der IDE Variabeln usw. inspizieren und schrittweise weitergehen. Das gibts meist 2fach, einmal den kompletten Schritt weitergehen oder in den Schritt reingehen (zB bei Methodenaufrufen wird beim ersten die Methode komplett ausgeführt, beim zweiten springst du mit in die Methode rein und kannst dort schrittweise weitergehen). Ohne Breakpoints rasselt das nur komplett durch und ermöglicht dir nur im Fehlerfall (SigSev o.ä.) die letzten Variabeln zu inspizieren - du hast vermutlich keine Breakpoints gesetzt.


Anmelden zum Antworten